Je sais comment implémenter le IEnumerable non générique, comme ceci:
using System;
using System.Collections;
namespace ConsoleApplication33
{
class Program
{
static void Main(string[] args)
{
MyObjects myObjects = new MyObjects();
myObjects[0] = new MyObject() { Foo = "Hello", Bar = 1 };
myObjects[1] = new MyObject() { Foo = "World", Bar = 2 };
foreach (MyObject x in myObjects)
{
Console.WriteLine(x.Foo);
Console.WriteLine(x.Bar);
}
Console.ReadLine();
}
}
class MyObject
{
public string Foo { get; set; }
public int Bar { get; set; }
}
class MyObjects : IEnumerable
{
ArrayList mylist = new ArrayList();
public MyObject this[int index]
{
get { return (MyObject)mylist[index]; }
set { mylist.Insert(index, value); }
}
IEnumerator IEnumerable.GetEnumerator()
{
return mylist.GetEnumerator();
}
}
}
Cependant, j'ai aussi remarqué que IEnumerable a une version générique, IEnumerable<T>
, mais je ne sais pas comment l'implémenter.
Si j'ajoute using System.Collections.Generic;
à mes directives using, puis modifie:
class MyObjects : IEnumerable
à:
class MyObjects : IEnumerable<MyObject>
Cliquez ensuite avec le bouton droit de la souris sur IEnumerable<MyObject>
et sélectionnez Implement Interface => Implement Interface
. Visual Studio ajoute utilement le bloc de code suivant:
IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
throw new NotImplementedException();
}
Renvoyer l'objet IEnumerable non générique à partir de la méthode GetEnumerator();
ne fonctionne pas cette fois-ci, alors qu'est-ce que je mets ici? La CLI ignore maintenant l'implémentation non générique et se dirige directement vers la version générique lorsqu'elle tente d'énumérer dans mon tableau au cours de la boucle foreach.
Si vous choisissez d'utiliser une collection générique, telle que List<MyObject>
au lieu de ArrayList
, le List<MyObject>
fournira des énumérateurs génériques et non génériques que vous pourrez utiliser.
using System.Collections;
class MyObjects : IEnumerable<MyObject>
{
List<MyObject> mylist = new List<MyObject>();
public MyObject this[int index]
{
get { return mylist[index]; }
set { mylist.Insert(index, value); }
}
public IEnumerator<MyObject> GetEnumerator()
{
return mylist.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Vous ne voulez probablement pas une implémentation de explicite de IEnumerable<T>
(ce que vous avez montré).
Le modèle habituel est d'utiliser IEnumerable<T>
'GetEnumerator
dans l'implémentation explicite de IEnumerable
:
class FooCollection : IEnumerable<Foo>, IEnumerable
{
SomeCollection<Foo> foos;
// Explicit for IEnumerable because weakly typed collections are Bad
System.Collections.IEnumerator IEnumerable.GetEnumerator()
{
// uses the strongly typed IEnumerable<T> implementation
return this.GetEnumerator();
}
// Normal implementation for IEnumerable<T>
IEnumerator<Foo> GetEnumerator()
{
foreach (Foo foo in this.foos)
{
yield return foo;
//nb: if SomeCollection is not strongly-typed use a cast:
// yield return (Foo)foo;
// Or better yet, switch to an internal collection which is
// strongly-typed. Such as List<T> or T[], your choice.
}
// or, as pointed out: return this.foos.GetEnumerator();
}
}
Pourquoi le faites-vous manuellement? yield return
automatise l'intégralité du processus de traitement des itérateurs. (J'ai aussi écrit à ce sujet sur mon blog , y compris un aperçu du code généré par le compilateur).
Si vous voulez vraiment le faire vous-même, vous devez également renvoyer un énumérateur générique. Vous ne pourrez plus utiliser un ArrayList
puisque ce n'est pas générique. Remplacez-le par un _List<MyObject>
_. Bien entendu, cela suppose que vous n’ayez que des objets de type MyObject
(ou des types dérivés) dans votre collection.
Si vous travaillez avec des génériques, utilisez List au lieu de ArrayList. La liste contient exactement la méthode GetEnumerator dont vous avez besoin.
List<MyObject> myList = new List<MyObject>();
faire de mylist un List<MyObject>
, est une option