Sé cómo implementar el IEnumerable no genérico, así:
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();
}
}
}
Sin embargo, también noto que IEnumerable tiene una versión genérica IEnumerable<T>
, pero no puedo entender cómo implementarla.
Si agrego using System.Collections.Generic;
a mis directivas de uso y luego cambio:
class MyObjects : IEnumerable
a:
class MyObjects : IEnumerable<MyObject>
Y luego haga clic derecho IEnumerable<MyObject>
y seleccione Implement Interface => Implement Interface
, Visual Studio agrega útilmente el siguiente bloque de código:
IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
throw new NotImplementedException();
}
Devolver el objeto IEnumerable no genérico del GetEnumerator();
método no funciona esta vez, entonces, ¿qué pongo aquí? La CLI ahora ignora la implementación no genérica y se dirige directamente a la versión genérica cuando intenta enumerar a través de mi matriz durante el ciclo foreach.
this.GetEnumerator()
y simplemente regresarGetEnumerator()
?Collection<MyObject>
y luego no tendrá que escribir ningún código personalizado.List<T>
e implementarIEnumerable<T>
como se muestra en su respuesta.Probablemente no desee una implementación explícita de
IEnumerable<T>
(que es lo que ha mostrado).El patrón habitual es usar
IEnumerable<T>
'sGetEnumerator
en la implementación explícita deIEnumerable
:fuente
IEnumerable
es redundante (IEnumerable<T>
ya se hereda de ella).¿Por qué lo haces manualmente?
yield return
automatiza todo el proceso de manejo de iteradores. (También escribí sobre eso en mi blog , incluyendo un vistazo al código generado por el compilador).Si realmente desea hacerlo usted mismo, también debe devolver un enumerador genérico. Ya no podrá usar uno
ArrayList
ya que no es genérico. Cámbielo a unList<MyObject>
lugar. Eso, por supuesto, supone que solo tiene objetos de tipoMyObject
(o tipos derivados) en su colección.fuente
yield return
. Asumí erróneamente que había un procesamiento personalizado.Si trabaja con genéricos, use List en lugar de ArrayList. La lista tiene exactamente el método GetEnumerator que necesita.
fuente
convertir mi lista en una
List<MyObject>
, es una opciónfuente
Tenga en cuenta que el enfoque ya
IEnumerable<T>
implementado porSystem.Collections
lo que otro enfoque es derivar suMyObjects
claseSystem.Collections
como una clase base ( documentación ):Después podemos hacer nuestra propia implemenation para anular los virtuales
System.Collections
métodos para proporcionar un comportamiento personalizado (sólo paraClearItems
,InsertItem
,RemoveItem
, ySetItem
junto con elEquals
,GetHashCode
yToString
desdeObject
). A diferencia delList<T>
que no está diseñado para ser fácilmente extensible.Ejemplo:
Tenga en cuenta que conducir
collection
solo se recomienda en caso de que se necesite un comportamiento de recolección personalizado, lo que rara vez ocurre. ver uso .fuente