IEnumerable<T>をテンプレート引数が異なるIEnumerable<T’> where T : T’ に変換したい場合がしばしばある。

普通にキャストすると

IEnumerable tEnumerable = (IEnumerable)tConcreteEnumerable;

コンパイルは通るけど実行時に例外が起きてしまう。

System.Reflection.TargetInvocationException: 呼び出しのターゲットが例外をスローしました。 ---> System.InvalidCastException: 型 'System.Collections.Generic.List`1[ConcreteType]' のオブジェクトを型 'System.Collections.Generic.IEnumerable`1[AbstractType]' にキャストできません。

↑こんな感じ。

そんなときは、以下の詰め替えクラスを作っておけばラクチン。

public class RepackingEnumerable : IEnumerable where InputType : OutputType
{
  private IEnumerable mInput;
  public RepackingEnumerable(IEnumerable aInput)
  {
    mInput = aInput;
  }

  public IEnumerator GetEnumerator()
  {
    foreach (OutputType tElement in mInput)
    {
      yield return tElement;
    }
  }

  IEnumerator IEnumerable.GetEnumerator()
  {
    return ((IEnumerable)mInput).GetEnumerator();
  }
};

使うときはこんな感じで。

IEnumerable tEnumerable = new RepackingEnumerable(tConcreteEnumerable);

yield returnなんて初めて使った(笑

カテゴリー: 技術情報