実際のコレクションを返すことと使用することの違いは、yield
返すオブジェクトの型だけです。
を実装するコレクションを返す場合IEnumerable<T>
、返されるオブジェクトの実際の型はその型になります。たとえば、 を返す場合、List<T>
返される参照はIEnumerable<T>
型になりますが、参照が指すオブジェクトの実際の型は のインスタンスですList<T>
。
を使用するyield
と、コンパイラは既知の名前のない列挙子オブジェクトを作成します。返される参照の型も になりIEnumerable<T>
ますが、参照が指すオブジェクトの実際の型は、コンパイラが作成するものになります。
たとえば、整数に対して作成された列挙子の型の名前を取得します。
Console.WriteLine(Cat<int>(42).GetType().Name);
たとえば、コードから得た次の結果など、コンパイラが使用する内部名が表示されます。
<Cat>d__5`1
関数がList<int>
代わりに a を返す場合、型は次のように表示されます。
List`1
コンパイラにこれの列挙子を作成させる動機は、おそらく次のようなものよりも短いということです。
static IEnumerable<T> Cat<T>(T t) {
List<T> list = new List<T>(1);
list.Add(t);
return list;
}
(C# の新しいバージョンでは、ショートカットを使用して少し短く書くことができますが、それでもyield
.
型がコレクションの場合、参照を実際の型にキャストして、コレクション内の値を変更できます。
IEnumerable<int> ienum = Cat<int>(42);
((List<int>)ienum)[0] = 1337;
foreach (int value in ienum) {
Console.WriteLine(value);
}
出力します:
1337