Eu sei como implementar o IEnumerable não genérico, assim:
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();
}
}
}
No entanto, também notei que o IEnumerable tem uma versão genérica IEnumerable<T>
, mas não consigo descobrir como implementá-lo.
Se eu adicionar using System.Collections.Generic;
ao meu uso diretivas, e depois alterar:
class MyObjects : IEnumerable
para:
class MyObjects : IEnumerable<MyObject>
E, em seguida, clique com o botão direito do mouse IEnumerable<MyObject>
e selecione Implement Interface => Implement Interface
, o Visual Studio adiciona o seguinte bloco de código:
IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
throw new NotImplementedException();
}
Retornar o objeto IEnumerable não genérico do GetEnumerator();
método não funciona desta vez, então o que devo colocar aqui? A CLI agora ignora a implementação não genérica e segue diretamente para a versão genérica quando tenta enumerar minha matriz durante o loop foreach.
this.GetEnumerator()
e simplesmente retornarGetEnumerator()
?Collection<MyObject>
e não precisará escrever nenhum código personalizado.List<T>
e implementarIEnumerable<T>
como mostrado na sua resposta.Você provavelmente não deseja uma implementação explícita de
IEnumerable<T>
(que é o que você mostrou).O padrão usual é usar
IEnumerable<T>
's'GetEnumerator
na implementação explícita deIEnumerable
:fonte
IEnumerable
é redundante (IEnumerable<T>
já herda dela).Por que você faz isso manualmente?
yield return
automatiza todo o processo de manipulação de iteradores. (Eu também escrevi sobre isso no meu blog , incluindo uma olhada no código gerado pelo compilador).Se você realmente deseja fazer isso sozinho, também precisará retornar um enumerador genérico. Você não poderá mais usar um,
ArrayList
uma vez que não é genérico. Altere para um emList<MyObject>
vez disso. Obviamente, isso pressupõe que você tenha apenas objetos do tipoMyObject
(ou tipos derivados) em sua coleção.fonte
yield return
. Eu assumi erroneamente que havia algum processamento personalizado.Se você trabalha com genéricos, use Lista em vez de ArrayList. A lista possui exatamente o método GetEnumerator que você precisa.
fonte
transformar minha lista em uma
List<MyObject>
é uma opçãofonte
Observe que o
IEnumerable<T>
método já implementado pelaSystem.Collections
outra abordagem é derivar suaMyObjects
classeSystem.Collections
como uma classe base ( documentação ):Mais tarde, pode fazer nossa própria implemenation para substituir as virtuais
System.Collections
métodos para fornecer o comportamento personalizado (apenas paraClearItems
,InsertItem
,RemoveItem
e,SetItem
juntamente comEquals
,GetHashCode
e,ToString
a partirObject
). Ao contrário doList<T>
que não foi projetado para ser facilmente extensível.Exemplo:
Observe que a orientação é
collection
apenas recomendada caso seja necessário um comportamento de coleção personalizado, o que raramente acontece. veja o uso .fonte