96 votes

obtenir un énumérateur générique à partir d'un tableau

En C#, comment obtenir un énumérateur générique à partir d'un tableau donné ?

Dans le code ci-dessous, MyArray est un tableau de MyType des objets. J'aimerais obtenir MyIEnumerator de la manière indiquée, mais il semble que j'obtienne un énumérateur vide (bien que j'ai confirmé que MyArray.Length > 0 ).

MyType [ ]  MyArray  =  ... ;
IEnumerator<MyType>  MyIEnumerator
  =  ( MyArray.GetEnumerator() as IEnumerator<MyType> ) ;

109voto

Mehrdad Afshari Points 204872

Fonctionne sur 2.0+ :

((IEnumerable<MyType>)myArray).GetEnumerator()

Fonctionne sur 3.5+ (fantaisie LINQy, un peu moins efficace) :

myArray.Cast<MyType>().GetEnumerator()   // returns IEnumerator<MyType>

59voto

Glenn Slayden Points 1995

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 ?

24voto

greenoldman Points 4575

Comme je n'aime pas les castings, une petite mise à jour :

your_array.AsEnumerable().GetEnumerator();

6voto

leat Points 466

Pour le rendre aussi propre que possible, je préfère laisser le compilateur faire tout le travail. Il n'y a pas de casts (donc c'est réellement sûr au niveau du type). Aucune bibliothèque tierce (System.Linq) n'est utilisée (pas de frais d'exécution).

    public static IEnumerable<T> GetEnumerable<T>(this T[] arr)
    {
        return arr;
    }

// Et pour utiliser le code :

    String[] arr = new String[0];
    arr.GetEnumerable().GetEnumerator()

Cela permet de tirer parti d'une certaine magie du compilateur qui garde tout propre.

L'autre point à noter est que c'est la seule réponse qui fera réellement une vérification au moment de la compilation, ce qui signifie que si le type de "arr" change, alors votre code compilera, mais aura un bug à l'exécution. Le mien ne compilera pas et j'ai donc moins de chances d'envoyer un bogue dans mon code. En effet, cela me signalerait que j'utilise le mauvais type.

2voto

Andrew Dennison Points 26

YourArray.OfType().GetEnumerator() ;

peut être un peu plus performant, puisqu'il n'a qu'à vérifier le type, et ne pas effectuer de cast.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X