Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье показано, как использовать IEnumerable интерфейсы для IEnumerator создания класса, который можно использовать в инструкции foreach .
Исходная версия продукта: Visual Studio
Исходный номер базы знаний: 322022
Интерфейс IEnumerator
IEnumerable и IEnumerator часто используются вместе. Хотя эти интерфейсы похожи (и имеют аналогичные имена), они имеют разные цели.
Интерфейс IEnumerator предоставляет итеративную возможность для коллекции, которая является внутренней для класса. IEnumerator требуется реализовать три метода:
Метод
MoveNext, который увеличивает индекс коллекции на 1 и возвращает логическое значение, указывающее, достигнут ли конец коллекции.Метод
Reset, который сбрасывает индекс коллекции до начального значения -1. Это делает перечисление недействительным.Метод, возвращающий
Currentтекущий объект вposition.public bool MoveNext() { position++; return (position < carlist.Length); } public void Reset() { position = -1; } public object Current { get { return carlist[position];} }
Интерфейс IEnumerable
Интерфейс IEnumerable обеспечивает поддержку foreach итерации. IEnumerable требуется реализовать GetEnumerator метод.
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
Когда следует использовать интерфейс
Изначально может возникнуть путаница в использовании этих интерфейсов. Интерфейс IEnumerator предоставляет итерацию по объекту типа коллекции в классе. Интерфейс IEnumerable разрешает перечисление с помощью foreach цикла. GetEnumerator Однако метод IEnumerable интерфейса возвращает IEnumerator интерфейс. Поэтому для реализации IEnumerableнеобходимо также реализовать IEnumerator. Если вы не реализуете IEnumerator, вы не можете привести возвращаемое значение из GetEnumerator метода IEnumerable интерфейса IEnumerator .
В целом, использование IEnumerable этого класса требует реализации IEnumeratorкласса. Если вы хотите предоставить поддержку foreach, реализуйте оба интерфейса.
Пошаговый пример
В следующем примере показано, как использовать эти интерфейсы. В этом примере IEnumerator интерфейсы используются IEnumerable в классе с именем cars. Класс cars имеет внутренний массив car объектов. Клиентские приложения могут перечислять этот внутренний foreach массив с помощью конструкции из-за реализации этих двух интерфейсов.
Выполните следующие действия, чтобы создать проект консольного приложения в Visual C#:
- Запустите Microsoft Visual Studio .NET или Visual Studio.
- В меню Файл выберите пункт Создать и затем пункт Проект.
- Нажмите Проекты Visual C# в разделе Типы проектов, а затем нажмите Консольное приложение в разделе Шаблоны.
- В поле "Имя" введите ConsoleEnum.
Переименуйте Class1.cs на host.cs, а затем замените код в host.cs следующим кодом:
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(); } } }В меню "Проект" нажмите кнопку "Добавить класс", а затем введите автомобиль в поле "Имя".
Замените код в car.cs следующим кодом:
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В меню "Проект" нажмите кнопку "Добавить класс", чтобы добавить другой класс в проект, а затем введите автомобили в поле "Имя".
Замените код в cars.cs следующим кодом:
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];} } } }Запустите проект.
В окне консоли отображаются следующие выходные данные:
Ford 1992
Fiat 1988
Buick 1932
Ford 1932
Dodge 1999
Honda 1977
Рекомендации
Пример, приведенный в этой статье, хранится как можно проще, чтобы лучше объяснить использование этих интерфейсов. Чтобы сделать код более надежным и убедиться, что код использует текущие рекомендации, измените код следующим образом:
- Реализуйте
IEnumeratorвложенном классе, чтобы создать несколько перечислителей. - Предоставьте обработку исключений
CurrentIEnumeratorдля метода . Если содержимое коллекции изменяется,resetвызывается метод. В результате текущий перечислитель недопустим, и вы получаетеIndexOutOfRangeExceptionисключение. Другие обстоятельства также могут вызвать это исключение. Поэтому реализуйте блок для перехватаTry...Catchэтого исключения и созданияInvalidOperationExceptionисключения.
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);
}
}
}