¿Cómo puedo implementar IEnumerable
Sé cómo implementar elerableumerable 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 Iumerable tiene una versión genérica, IEnumerable<T>
, pero no puedo averiguar cómo implementarla.
Si añado 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 en IEnumerable<MyObject>
y seleccione Implement Interface => Implement Interface
, Visual Studio agrega el siguiente bloque de código:
IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
throw new NotImplementedException();
}
Devolviendo el objeto genericumerable no genérico desde el GetEnumerator();
el método no funciona esta vez, así que ¿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 bucle foreach.
6 answers
Si elige usar una colección genérica, como List<MyObject>
en lugar de ArrayList
, encontrará que List<MyObject>
proporcionará enumeradores genéricos y no genéricos que puede usar.
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();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-11 18:56:00
Probablemente no quieras una implementación explícita de IEnumerable<T>
(que es lo que has mostrado).
El patrón habitual es usar el GetEnumerator de IEnumerable<T>
en la implementación explícita deerableumerable:
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();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-02 15:58:32
¿por Qué lo haces manualmente? yield return
automatiza todo el proceso de manejo de iteradores. (También escribí sobre ello en mi blog, incluyendo un vistazo al código generado por el compilador).
Si realmente quieres hacerlo tú mismo, también tienes que devolver un enumerador genérico. Ya no podrás usar un ArrayList
ya que no es genérico. Cámbialo a List<MyObject>
en su lugar. Eso, por supuesto, supone que solo tiene objetos de tipo MyObject
(o tipos derivados) en su colección.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-02 15:50:57
Si trabaja con genéricos, use List en lugar de ArrayList. La Lista tiene exactamente el método GetEnumerator que necesita.
List<MyObject> myList = new List<MyObject>();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-02 15:42:15
Hacer mylist en un List<MyObject>
, es una opción
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-02 15:40:12
Tenga en cuenta que el IEnumerable<T>
ya está implementado por el System.Collections
por lo que otro enfoque es derivar su clase MyObjects
de System.Collections
como una clase base (documentación):
Sistema.Colecciones: Proporciona la clase base para una colección genérica.
Más tarde podemos hacer nuestra propia implementación para anular los métodos virtuales System.Collections
para proporcionar un comportamiento personalizado (solo para ClearItems
, InsertItem
, RemoveItem
, y SetItem
junto con Equals
, GetHashCode
, y ToString
de Object
). A diferencia de la List<T>
que no está diseñado para ser fácilmente extensible.
Ejemplo:
public class FooCollection : System.Collections<Foo>
{
//...
protected override void InsertItem(int index, Foo newItem)
{
base.InsertItem(index, newItem);
Console.Write("An item was successfully inserted to MyCollection!");
}
}
public static void Main()
{
FooCollection fooCollection = new FooCollection();
fooCollection.Add(new Foo()); //OUTPUT: An item was successfully inserted to FooCollection!
}
Tenga en cuenta que conducir desde collection
solo se recomienda en caso de que se necesite un comportamiento de recopilación personalizado, lo que rara vez ocurre. ver uso .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-02 21:07:36