Может ли кто-нибудь объяснить мне IEnumerable и IEnumerator?

Интерфейсы IEnumerable и IEnumerator

Чтобы приступить к изучению ienumerator процесса реализации существующих c#-language интерфейсов .NET, давайте csharp сначала рассмотрим роль IEnumerable visual-c# и IEnumerator. Напомним, что visual-c# C# поддерживает ключевое c# слово с именем foreach, которое c#.net позволяет вам перебирать c-sharp содержимое любого типа массива:

// Iterate over an array of items.
int[] myArrayOfInts = {10, 20, 30, 40};
foreach(int i in myArrayOfInts)
{
   Console.WriteLine(i);
}

Хотя visual-c# может показаться, что эту ienumerator конструкцию могут использовать visual-c# только типы массивов, на visual-c# самом деле любой тип, поддерживающий c#-language метод с именем GetEnumerator(), может ienumerable быть оценен конструкцией csharp foreach. проиллюстрируйте, следуйте c#.net за мной!

Предположим, у нас ienumerator есть класс Garage:

// Garage contains a set of Car objects.
public class Garage
{
   private Car[] carArray = new Car[4];
   // Fill with some Car objects upon startup.
   public Garage()
   {
      carArray[0] = new Car("Rusty", 30);
      carArray[1] = new Car("Clunker", 55);
      carArray[2] = new Car("Zippy", 30);
      carArray[3] = new Car("Fred", 30);
   }
}

В идеале .cs-file было бы удобно перебирать ienumerator подпункты объекта Garage csharp с помощью команды foreach построить, как ienumerable массив значений данных:

// This seems reasonable ...
public class Program
{
   static void Main(string[] args)
   {
      Console.WriteLine("***** Fun with IEnumerable / IEnumerator *****\n");
      Garage carLot = new Garage();
      // Hand over each car in the collection?
      foreach (Car c in carLot)
      {
         Console.WriteLine("{0} is going {1} MPH",
         c.PetName, c.CurrentSpeed);
      }
      Console.ReadLine();
   }
}

К ienumerable сожалению, компилятор сообщает, что csharp класс Garage не реализует c#-language метод с именем GetEnumerator(). Этот visual-c# метод формализован интерфейсом c#.net IEnumerable, который скрывается ienumerator в пространстве имен System.Collections. Классы .cs-file или структуры, поддерживающие ienumerator такое поведение, объявляют, что c-sharp они могут раскрыть содержащиеся subitems .cs-file вызывающему (в этом примере c-sharp само ключевое слово foreach). Вот visual-c# определение этого стандартного c# интерфейса .NET:

// This interface informs the caller
// that the object's subitems can be enumerated.
public interface IEnumerable
{
   IEnumerator GetEnumerator();
}

Как видите, метод csharp GetEnumerator() возвращает c-sharp ссылку на еще один интерфейс c-sharp с именем System.Collections.IEnumerator. Этот ienumerable интерфейс предоставляет инфраструктуру, позволяющую visual-c# вызывающей стороне перемещаться c#-language по внутренним объектам, содержащимся c# в IEnumerable-совместимом c#-language контейнере:

// This interface allows the caller to
// obtain a container's subitems.
public interface IEnumerator
{
   bool MoveNext (); // Advance the internal position of the cursor.
   object Current { get;} // Get the current item (read-only property).
   void Reset (); // Reset the cursor before the first member.
}

Если вы хотите visual-c# обновить тип Garage для поддержки ienumerator этих интерфейсов, вы можете visual-c# пойти по долгому пути и реализовать ienumerable каждый метод вручную. Хотя c#.net вы, безусловно, можете предоставить csharp индивидуальные версии GetEnumerator(), MoveNext(), Current .cs-file и Reset(), есть более простой visual-c# способ. Поскольку тип System.Array ienumerator (как и многие другие классы .cs-file коллекций) уже реализует visual-c# IEnumerable и IEnumerator, вы .cs-file можете просто делегировать c# запрос в System.Array следующим c# образом:

using System.Collections;
...
public class Garage : IEnumerable
{
   // System.Array already implements IEnumerator!
   private Car[] carArray = new Car[4];
   public Garage()
   {
      carArray[0] = new Car("FeeFee", 200);
      carArray[1] = new Car("Clunker", 90);
      carArray[2] = new Car("Zippy", 30);
      carArray[3] = new Car("Fred", 30);
   }
   public IEnumerator GetEnumerator()
   {
      // Return the array object's IEnumerator.
      return carArray.GetEnumerator();
   }
}

После обновления c-sharp типа Garage его можно безопасно csharp использовать в конструкции visual-c# C# foreach. Кроме того, учитывая, что c# метод GetEnumerator() был ienumerator определен публично, пользователь c#.net объекта также может взаимодействовать c-sharp с типом IEnumerator:

// Manually work with IEnumerator.
IEnumerator i = carLot.GetEnumerator();
i.MoveNext();
Car myCar = (Car)i.Current;
Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrentSpeed);

Однако, если c# вы предпочитаете скрыть функциональность ienumerator IEnumerable на уровне объекта, просто .cs-file сделайте использование явной visual-c# реализации интерфейса:

IEnumerator IEnumerable.GetEnumerator()
{
  // Return the array object's IEnumerator.
  return carArray.GetEnumerator();
}

Таким ienumerator образом, пользователь случайного c# объекта не найдет метод GetEnumerator() Garage, в c#.net то время как Конструкция c#.net foreach при необходимости ienumerable получит интерфейс в фоновом ienumerator режиме.

Адаптировано из Pro C# 5.0 and the .NET 4.5 Framework

c#

ienumerable

ienumerator

2022-10-27T22:24:32+00:00