キャストが不適なライブラリ呼び出しを正当化するのに十分醜いかどうかを自分で決めることができます。
int[] arr;
IEnumerator<int> Get1()
{
return ((IEnumerable<int>)arr).GetEnumerator(); // <-- 1 non-local call
// ldarg.0
// ldfld int32[] foo::arr
// castclass System.Collections.Generic.IEnumerable`1<int32>
// callvirt instance class System.Collections.Generic.IEnumerator`1<!0> System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
}
IEnumerator<int> Get2()
{
return arr.AsEnumerable().GetEnumerator(); // <-- 2 non-local calls
// ldarg.0
// ldfld int32[] foo::arr
// call class System.Collections.Generic.IEnumerable`1<!!0> System.Linq.Enumerable::AsEnumerable<int32>(class System.Collections.Generic.IEnumerable`1<!!0>)
// callvirt instance class System.Collections.Generic.IEnumerator`1<!0> System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
}
また、完全を期すために、デフォルトの(つまり非明示的な)実装に非ジェネリックインターフェイスをT[]
選択するため、以下は正しくなく、実行時にクラッシュすることに注意する必要があります。IEnumerable
GetEnumerator()
IEnumerator<int> NoGet() // error - do not use
{
return (IEnumerator<int>)arr.GetEnumerator();
// ldarg.0
// ldfld int32[] foo::arr
// callvirt instance class System.Collections.IEnumerator System.Array::GetEnumerator()
// castclass System.Collections.Generic.IEnumerator`1<int32>
}
謎は、なぜ(現在「封印された」とマークされている内部クラス)SZGenericArrayEnumerator<T>
から継承しないSZArrayEnumerator
のですか?これにより、(共変)ジェネリック列挙子がデフォルトで返されるようになるためです。