Hacer que una clase de Visual C# se pueda usar en una instrucción foreach
En este artículo se muestra cómo usar las IEnumerable
interfaces y IEnumerator
para crear una clase que se puede usar en una foreach
instrucción .
Versión del producto original: Visual Studio
Número de KB original: 322022
Interfaz IEnumerator
IEnumerable
y IEnumerator
se usan con frecuencia juntos. Aunque estas interfaces son similares (y tienen nombres similares), tienen propósitos diferentes.
La IEnumerator
interfaz proporciona funcionalidad iterativa para una colección que es interna para una clase. IEnumerator
requiere que implemente tres métodos:
El
MoveNext
método , que incrementa el índice de colección en 1 y devuelve un bool que indica si se ha alcanzado el final de la colección.El
Reset
método , que restablece el índice de colección a su valor inicial de -1. Esto invalida el enumerador.Método
Current
, que devuelve el objeto actual enposition
.public bool MoveNext() { position++; return (position < carlist.Length); } public void Reset() { position = -1; } public object Current { get { return carlist[position];} }
Interfaz IEnumerable
La IEnumerable
interfaz proporciona compatibilidad con la foreach
iteración. IEnumerable
requiere que implemente el GetEnumerator
método .
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
Cuándo usar la interfaz
Inicialmente, es posible que le resulte confuso usar estas interfaces. La IEnumerator
interfaz proporciona iteración sobre un objeto de tipo colección en una clase. La IEnumerable
interfaz permite la enumeración mediante un foreach
bucle . Sin embargo, el GetEnumerator
método de la IEnumerable
interfaz devuelve una IEnumerator
interfaz. Por lo tanto, para implementar IEnumerable
, también debe implementar IEnumerator
. Si no implementa IEnumerator
, no puede convertir el valor devuelto desde el GetEnumerator
método de IEnumerable
a la IEnumerator
interfaz.
En resumen, el uso de IEnumerable
requiere que la clase implemente IEnumerator
. Si desea proporcionar compatibilidad con foreach
, implemente ambas interfaces.
Ejemplo paso a paso
En el ejemplo siguiente se muestra cómo usar estas interfaces. En este ejemplo, las IEnumerator
interfaces y IEnumerable
se usan en una clase denominada cars
. La cars
clase tiene una matriz interna de car
objetos. Las aplicaciones cliente pueden enumerarse a través de esta matriz interna mediante una foreach
construcción debido a la implementación de estas dos interfaces.
Siga estos pasos para crear un nuevo proyecto de aplicación de consola en Visual C#:
- Inicie Microsoft Visual Studio .NET o Visual Studio.
- En el menú Archivo, elija Nuevo y, a continuación, haga clic en Proyecto.
- Haga clic en Proyectos en Visual C# en Tipos de proyecto y luego haga clic en Aplicación de consola en Plantillas.
- En el cuadro Nombre , escriba ConsoleEnum.
Cambie el nombre de Class1.cs a host.cs y, a continuación, reemplace el código de host.cs por el código siguiente:
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(); } } }
En el menú Proyecto , haga clic en Agregar clase y, a continuación, escriba car en el cuadro Nombre .
Reemplace el código de car.cs por el código siguiente:
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
En el menú Proyecto , haga clic en Agregar clase para agregar otra clase al proyecto y, a continuación, escriba cars en el cuadro Nombre .
Reemplace el código de cars.cs por el código siguiente:
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];} } } }
Ejecute el proyecto.
La siguiente salida aparece en la ventana Consola :
Ford 1992
Fiat 1988
Buick 1932
Ford 1932
Dodge 1999
Honda 1977
Procedimientos recomendados
El ejemplo de este artículo se mantiene lo más sencillo posible para explicar mejor el uso de estas interfaces. Para que el código sea más sólido y para asegurarse de que el código usa las directrices de procedimientos recomendados actuales, modifique el código de la siguiente manera:
- Implemente
IEnumerator
en una clase anidada para que pueda crear varios enumeradores. - Proporcione el control de excepciones para el
Current
método deIEnumerator
. Si cambia el contenido de la colección, se llama alreset
método . Como resultado, el enumerador actual se invalida y recibe unaIndexOutOfRangeException
excepción. Otras circunstancias también pueden provocar esta excepción. Por lo tanto, implemente unTry...Catch
bloque para detectar esta excepción y generar unaInvalidOperationException
excepción.
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);
}
}
}
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de