読者です 読者をやめる 読者になる 読者になる

【C#】IEnumerable<dynamic>の作り方

IEnumerable<dynamic>を継承するクラスを作成しようとするとビルド時に
動的なインターフェイス ‘System.Collections.Generic.IEnumerable<dynamic>’ を実装できません と表示される。

dynamicで受け取るオブジェクトがGetEnumeratorを実装していれば普通にforeachでいいんだけど、LINQが使えない。
特にCOM相互運用のオブジェクト、って言うか、ExcelのRange。あれはGetEnumeratorメソッドを持っているし、LINQをバリバリ使いたいオブジェクトの一つなので、IEnumerable<dynamic>を実装したラッパーを作りたいケースがまったくないわけでもない。

そう言った場合はIEnumerable<T>を継承してやればいい。

コード

public class IDynamicEnumrable<T> : IEnumerable<T>
{
    private dynamic _range;

    public IDynamicEnumrable(dynamic range)
    {
        this._range = range;
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (var cell in _range) yield return cell;
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

}

後はnew IDynamicEnumrable<dynamic>してやればOK。

まとめ

当然IEnumerable<T>で宣言しているためdynamic以外も指定出来てしまうので、型安全も何もないが、Tの代わりに渡したいdynamicの妥当性を検証するだけのクラス、もしくは使いたいプロパティだけを抽出するクラスを作成し、それに置き換えるという手法もある。(そっちの方がメジャーな手法らしい)

色々探してみると拡張メソッドでLINQのメソッドを新たに追加すると言う方法をとってる人がいたが、this objectを指定するのは、なんかこう、アレじゃないですかね?