Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье показано, как использовать 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
вложенном классе, чтобы создать несколько перечислителей. - Предоставьте обработку исключений
Current
IEnumerator
для метода . Если содержимое коллекции изменяется,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);
}
}
}