Tornar uma classe do Visual C# utilizável em uma instrução foreach
Este artigo demonstra como usar as IEnumerable
interfaces e IEnumerator
para criar uma classe que você pode usar em uma foreach
instrução.
Versão original do produto: Visual Studio
Número de KB original: 322022
Interface IEnumerator
IEnumerable
e IEnumerator
são usados com frequência juntos. Embora essas interfaces sejam semelhantes (e tenham nomes semelhantes), elas têm propósitos diferentes.
A IEnumerator
interface fornece recursos iterativos para uma coleção que é interna para uma classe. IEnumerator
exige que você implemente três métodos:
O
MoveNext
método, que incrementa o índice de coleção em 1 e retorna um bool que indica se o final da coleção foi atingido.O
Reset
método, que redefine o índice de coleção para seu valor inicial de -1. Isso invalida o enumerador.O
Current
método, que retorna o objeto atual emposition
.public bool MoveNext() { position++; return (position < carlist.Length); } public void Reset() { position = -1; } public object Current { get { return carlist[position];} }
Interface IEnumerable
A IEnumerable
interface fornece suporte para a foreach
iteração. IEnumerable
exige que você implemente o GetEnumerator
método.
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
Quando usar qual interface
Inicialmente, você pode achar confuso usar essas interfaces. A IEnumerator
interface fornece iteração sobre um objeto tipo de coleção em uma classe. A IEnumerable
interface permite a enumeração usando um foreach
loop. No entanto, o GetEnumerator
método da IEnumerable
interface retorna uma IEnumerator
interface. Portanto, para implementar IEnumerable
, você também deve implementar IEnumerator
. Se você não implementar IEnumerator
, não poderá lançar o valor retornado do GetEnumerator
método de IEnumerable
para a IEnumerator
interface.
Em resumo, o uso de IEnumerable
requer que a classe implemente IEnumerator
. Se você quiser fornecer suporte para foreach
, implemente ambas as interfaces.
Exemplo passo a passo
O exemplo a seguir demonstra como usar essas interfaces. Neste exemplo, as IEnumerator
interfaces e IEnumerable
são usadas em uma classe chamada cars
. A cars
classe tem uma matriz interna de car
objetos. Os aplicativos cliente podem enumerar por meio dessa matriz interna usando um foreach
constructo devido à implementação dessas duas interfaces.
Siga estas etapas para criar um novo projeto de Aplicativo de Console no Visual C#:
- Inicie o Microsoft Visual Studio .NET ou o Visual Studio.
- No menu arquivo, aponte para novo e, em seguida, clique em Project.
- Clique em Projetos do Visual C# em Tipos de Projeto e, em seguida, clique em Aplicativo de Console em Modelos.
- Na caixa Nome , digite ConsoleEnum.
Renomeie Class1.cs para host.cs e substitua o código no host.cs pelo seguinte código:
using System; namespace ConsoleEnum { class host { [STAThread] static void Main(string[] args) { cars C = new cars(); Console.WriteLine("\nInternal Collection (Unsorted - IEnumerable,Enumerator)\n"); foreach(car c in C) Console.WriteLine(c.Make + "\t\t" + c.Year); Console.ReadLine(); } } }
No menu Projeto , clique em Adicionar Classe e digite carro na caixa Nome .
Substitua o código no car.cs pelo seguinte código:
using System; using System.Collections; namespace ConsoleEnum { public class car { private int year; private string make; public car(string Make,int Year) { make=Make; year=Year; } public int Year { get {return year;} set {year=value;} } public string Make { get {return make;} set {make=value;} } }//end class }//end namespace
No menu Projeto , clique em Adicionar Classe para adicionar outra classe ao projeto e digite carros na caixa Nome .
Substitua o código no cars.cs pelo seguinte código:
using System; using System.Collections; namespace ConsoleEnum { public class cars : IEnumerator,IEnumerable { private car[] carlist; int position = -1; //Create internal array in constructor. public cars() { carlist= new car[6] { new car("Ford",1992), new car("Fiat",1988), new car("Buick",1932), new car("Ford",1932), new car("Dodge",1999), new car("Honda",1977) }; } //IEnumerator and IEnumerable require these methods. public IEnumerator GetEnumerator() { return (IEnumerator)this; } //IEnumerator public bool MoveNext() { position++; return (position < carlist.Length); } //IEnumerable public void Reset() { position = -1; } //IEnumerable public object Current { get { return carlist[position];} } } }
Execute o projeto.
A saída a seguir é exibida na janela Console :
Ford 1992
Fiat 1988
Buick 1932
Ford 1932
Dodge 1999
Honda 1977
Práticas recomendadas
O exemplo neste artigo é mantido o mais simples possível para explicar melhor o uso dessas interfaces. Para tornar o código mais robusto e garantir que o código use as diretrizes de prática recomendada atuais, modifique o código da seguinte maneira:
- Implemente
IEnumerator
em uma classe aninhada para que você possa criar vários enumeradores. - Forneça tratamento de exceção para o
Current
método deIEnumerator
. Se o conteúdo da coleção for alterado, oreset
método será chamado. Como resultado, o enumerador atual é invalidado e você recebe uma exceçãoIndexOutOfRangeException
. Outras circunstâncias também podem causar essa exceção. Portanto, implemente umTry...Catch
bloco para capturar essa exceção e gerar uma exceçãoInvalidOperationException
.
using System;
using System.Collections;
namespace ConsoleEnum
{
public class cars : IEnumerable
{
private car[] carlist;
//Create internal array in constructor.
public cars()
{
carlist= new car[6]
{
new car("Ford",1992),
new car("Fiat",1988),
new car("Buick",1932),
new car("Ford",1932),
new car("Dodge",1999),
new car("Honda",1977)
};
}
//private enumerator class
private class MyEnumerator:IEnumerator
{
public car[] carlist;
int position = -1;
//constructor
public MyEnumerator(car[] list)
{
carlist=list;
}
private IEnumerator getEnumerator()
{
return (IEnumerator)this;
}
//IEnumerator
public bool MoveNext()
{
position++;
return (position < carlist.Length);
}
//IEnumerator
public void Reset()
{
position = -1;
}
//IEnumerator
public object Current
{
get
{
try
{
return carlist[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
} //end nested class
public IEnumerator GetEnumerator()
{
return new MyEnumerator(carlist);
}
}
}
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários