Vous pouvez décider par vous-même si le casting est suffisamment laid pour justifier un appel à la bibliothèque :
int[] arr;
IEnumerator<int> Get1()
{
return ((IEnumerable<int>)arr).GetEnumerator();
// L_0001: ldarg.0
// L_0002: ldfld int32[] agree.foo::arr
// L_0007: castclass [mscorlib]System.Collections.Generic.IEnumerable`1<int32>
// L_000c: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
// L_0011: stloc.0
}
IEnumerator<int> Get2()
{
return arr.AsEnumerable().GetEnumerator();
// L_0001: ldarg.0
// L_0002: ldfld int32[] agree.foo::arr
// L_0007: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::AsEnumerable<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
// L_000c: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
// L_0011: stloc.0
}
Et pour être complet, il faut également noter que ce qui suit n'est pas correct - et se plantera au moment de l'exécution - car T[]
choisit le non -générique IEnumerable
pour sa mise en œuvre par défaut (c'est-à-dire non explicite) de l'interface GetEnumerator()
.
IEnumerator<int> NoGet() // error - do not use
{
return (IEnumerator<int>)arr.GetEnumerator();
// L_0001: ldarg.0
// L_0002: ldfld int32[] agree.foo::arr
// L_0007: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Array::GetEnumerator()
// L_000c: castclass [mscorlib]System.Collections.Generic.IEnumerator`1<int32>
// L_0011: stloc.0
}
Le mystère est, pourquoi ne pas SZGenericArrayEnumerator<T>
hériter de SZArrayEnumerator
--une classe interne qui est actuellement marquée "sealed", puisque cela permettrait à l'énumérateur générique (covariant) d'être retourné par défaut ?