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

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

например, когда использовать его для foreach? какая разница между IEnumerable и IEnumerator? Зачем нам это нужно?

Ответ 1

например, когда использовать его для foreach?

Вы не используете IEnumerable "over" foreach. Реализация IEnumerable позволяет использовать foreach.

Когда вы пишете код, например:

foreach (Foo bar in baz)
{
   ...
}

он функционально эквивалентен записи:

IEnumerator bat = baz.GetEnumerator();
while (bat.MoveNext())
{
   bar = (Foo)bat.Current
   ...
}

Под "функционально эквивалентным" я подразумеваю, что на самом деле компилятор превращает код в. Вы не можете использовать foreach в baz в этом примере, если baz не реализует IEnumerable.

IEnumerable означает, что baz реализует метод

IEnumerator GetEnumerator()

Объект IEnumerator, возвращаемый этим методом, должен реализовать методы

bool MoveNext()

и

Object Current()

Первый метод продвигается к следующему объекту в объекте IEnumerable, который создал перечислитель, возвращая false, если он был сделан, а второй возвращает текущий объект.

Что-нибудь в .Net, что вы можете перебирать инструменты IEnumerable. Если вы создаете свой собственный класс и он еще не наследуется от класса, который реализует IEnumerable, вы можете сделать свой класс пригодным для использования в операторах foreach, реализовав IEnumerable (и создав класс перечислителя, новый метод GetEnumerator вернется).

Ответ 2

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

Чтобы начать изучение процесса внедрения существующих интерфейсов .NET, сначала рассмотрим роль IEnumerable и IEnumerator. Напомним, что С# поддерживает ключевое слово с именем foreach, которое позволяет вам итерации по содержимому любого типа массива:

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

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

Предположим, что у нас есть класс 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);
   }
}

В идеале было бы удобно перебирать подэлементы объектов Garage, используя foreach create, как и массив значений данных:

// 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();
   }
}

К сожалению, компилятор сообщает вам, что класс Garage не реализует метод с именем GetEnumerator(). Этот метод формализуется интерфейсом IEnumerable, который находится в пространстве имен System.Collections. Классы или структуры, которые поддерживают это поведение, рекламируют, что они могут подэлементы вызывающему абоненту (в этом примере используется ключевое слово foreach). Вот определение этого стандартного интерфейса .NET:

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

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

// This interface allows the caller to
// obtain a container 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.
}

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

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 IEnumerator.
      return carArray.GetEnumerator();
   }
}

После того, как вы обновили свой тип Garage, вы можете безопасно использовать тип внутри конструкции С# foreach. Кроме того, учитывая, что метод GetEnumerator() определен публично, пользователь объекта также может взаимодействовать с типом 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);

Однако, если вы предпочитаете скрывать функциональность IEnumerable с уровня объекта, просто сделайте использование явной реализации интерфейса:

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

Таким образом, пользователь случайного объекта не найдет метод Garages GetEnumerator(), а foreach construct получит интерфейс в фоновом режиме при необходимости.

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

Ответ 3

Реализация IEnumerable означает, что ваш класс возвращает объект IEnumerator:

public class People : IEnumerable
{
    IEnumerator IEnumerable.GetEnumerator()
    {
        // return a PeopleEnumerator
    }
}

Реализация IEnumerator означает, что ваш класс возвращает методы и свойства для итерации:

public class PeopleEnumerator : IEnumerator
{
    public void Reset()...

    public bool MoveNext()...

    public object Current...
}

В любом случае разница.

Ответ 4

Объяснение через Analogy + Code Walkthrough

Сначала объяснение без кода, потом я добавлю его позже.

Допустим, вы управляете авиакомпанией. И в каждом самолете вы хотите узнать информацию о пассажирах, летящих в самолете. В основном вы хотите, чтобы иметь возможность "пересечь" самолет. Другими словами, вы хотите иметь возможность начать с переднего сиденья, а затем направиться к задней части самолета, задавая пассажирам некоторую информацию: кто они, откуда они и т.д. Самолет может делать только это., если это:

  1. исчисляемый и
  2. если у него есть счетчик.

Почему эти требования? Потому что это то, что требует интерфейс.

Если это информационная перегрузка, вам нужно знать только то, что вы хотите задать каждому пассажиру в самолете несколько вопросов, начиная с первого и заканчивая последним.

Что значит счетное?

Если авиакомпания является "счетной", это означает, что в самолете ДОЛЖЕН присутствовать стюардесса, единственной задачей которой является подсчет - и эта стюардесса ДОЛЖНА вести подсчет весьма специфическим образом:

  1. Стойка/стюардесса ДОЛЖНА начинаться перед первым пассажиром (перед каждым, где они демонстрируют безопасность, как надеть спасательный жилет и т.д.).
  2. Он/она (т.е. Стюардесса) ДОЛЖЕН "двигаться дальше" по проходу к первому месту.
  3. Затем он/она должен записать: (i) кто находится на месте, и (ii) его текущее местоположение в проходе.

Процедуры подсчета

Капитан авиакомпании хочет получить отчет о каждом пассажире, когда и когда он расследуется или подсчитывается. Таким образом, после разговора с человеком на первом месте, стюардесса/счетчик затем сообщает капитану, и когда отчет предоставляется, счетчик запоминает его/ее точное положение в проходе и продолжает считать прямо там, где он/она покинул выкл.

Таким образом, капитан всегда может получить информацию о текущем человеке, находящемся под следствием. Таким образом, если он узнает, что этот человек любит Манчестер Сити, то он может предоставить этому пассажиру льготный режим и т.д.

  • Счетчик продолжает идти, пока он не достигнет конца самолета.

Давай свяжем это с IEnumerables

  • Enumerable - это просто набор пассажиров в самолете. Закон о гражданской авиации - это в основном правила, которым должны следовать все IEnumerables. Каждый раз, когда стюардесса отправляется к капитану с информацией о пассажирах, мы в основном "уступаем" пассажира капитану. Капитан может в основном делать с пассажиром все, что захочет, за исключением перестановки пассажиров в самолете. В этом случае им предоставляется преференциальный режим, если они следуют за Манчестер Сити (тьфу!)

    foreach (Passenger passenger in Plane)
    // the airline hostess is now at the front of the plane
    // and slowly making her way towards the back
    // when she get to a particular passenger she gets some information
    // about the passenger and then immediately heads to the cabin
    // to let the captain decide what to do with it
    { // <---------- Note the curly bracket that is here.
        // we are now cockpit of the plane with the captain.
        // the captain wants to give the passenger free 
        // champaign if they support manchester city
        if (passenger.supports_mancestercity())
        {
            passenger.getFreeChampaign();
        } else
        {
            // you get nothing! GOOD DAY SIR!
        }
    } //  <---- Note the curly bracket that is here!
          the hostess has delivered the information 
          to the captain and goes to the next person
          on the plane (if she has not reached the 
          end of the plane)
    

Резюме

Другими словами, что-то исчисляется, если у него есть счетчик. И счетчик должен (в основном): (i) помнить свое место (состояние), (ii) быть в состоянии двигаться дальше, (iii) и знать о текущем человеке, с которым он имеет дело.

Enumerable - это просто причудливое слово для "счетного". Другими словами, перечислимое позволяет вам "перечислять" (т.е. считать).

Ответ 5

IEnumerable реализует GetEnumerator. При вызове этот метод вернет IEnumerator, который реализует MoveNext, Reset и Current.

Таким образом, когда ваш класс реализует IEnumerable, вы говорите, что можете вызвать метод (GetEnumerator) и получить новый возвращаемый объект (IEnumerator), который вы можете использовать в цикле, таком как foreach.

Ответ 6

Реализация IEnumerable позволяет вам получить IEnumerator для списка.

IEnumerator позволяет обеспечить последовательный доступ к элементам списка в стиле foreach, используя ключевое слово yield.

Перед реализацией foreach (например, в Java 1.4) способ перебора списка состоял в том, чтобы получить перечислитель из списка, а затем спросить его о "следующем" элементе в списке до тех пор, пока возвращаемое значение поскольку следующий элемент не является нулевым. Foreach просто делает это неявно как функцию языка, так же, как lock() реализует класс Monitor за кулисами.

Я ожидаю, что foreach будет работать над списками, поскольку они реализуют IEnumerable.

Ответ 7

  • Объект, реализующий IEnumerable, позволяет другим посетителям каждого из своих элементов (посредством счетчика).
  • Объектом, реализующим IEnumerator, является выполнение итерации. Он перебирает перечислимый объект.

Подумайте о перечислимых объектах как о списках, стеках, деревьях.

Ответ 8

IEnumerable и IEnumerator (и их общие аналоги IEnumerable <T> и IEnumerator <T>) являются базовыми интерфейсами реализаций итераторов в коллекциях .ray Framework Class Libray.

IEnumerable является наиболее распространенным интерфейсом, который вы видите в большинстве кода. Он включает цикл foreach, генераторы (думаю, что выход) и, благодаря своему крошечному интерфейсу, используется для создания жестких абстракций. IEnumerable зависит от IEnumerator.

IEnumerator, с другой стороны, предоставляет интерфейс итерации немного более низкого уровня. Он называется явным итератором, который дает программисту больший контроль над циклом итерации.

IEnumerable

IEnumerable - это стандартный интерфейс, который позволяет перебирать коллекции, которые его поддерживают (фактически, все типы коллекций, о которых я могу думать сегодня, реализуют IEnumerable). Поддержка компилятора позволяет использовать языковые функции, такие как foreach. В общих чертах, это позволяет эту неявную реализацию итератора.

петля foreach

foreach (var value in list)
  Console.WriteLine(value);

Я думаю, что цикл foreach является одной из основных причин использования интерфейсов IEnumerable. foreach имеет очень лаконичный синтаксис и очень прост для понимания по сравнению с классическим стилем C для циклов, где вам нужно проверить различные переменные, чтобы увидеть, что он делает.

дать ключевое слово

Вероятно, менее известной особенностью является то, что IEnumerable также включает генераторы в С# с использованием операторов yield return и yield break.

IEnumerable<Thing> GetThings() {
   if (isNotReady) yield break;
   while (thereIsMore)
     yield return GetOneMoreThing();
}

Абстракции

Другой распространенный сценарий на практике - использование IEnumerable для предоставления минималистических абстракций. Поскольку это крошечный и доступный только для чтения интерфейс, рекомендуется представлять свои коллекции как IEnumerable (а не List, например). Таким образом, вы можете свободно изменять свою реализацию, не нарушая свой клиентский код (например, измените List на LinkedList).

Попался

Следует помнить об одном поведении: при потоковой реализации (например, извлечение данных строка за строкой из базы данных вместо загрузки сначала всех результатов в память) вы не можете перебирать коллекцию более одного раза. Это в отличие от коллекций в памяти, таких как List, где вы можете выполнять многократные итерации без проблем. ReSharper, например, имеет проверку кода для возможного множественного перечисления IEnumerable.

IEnumerator

IEnumerator, с другой стороны, является скрытым интерфейсом, который заставляет IEnumerble-foreach-magic работать. Строго говоря, он допускает явные итераторы.

var iter = list.GetEnumerator();
while (iter.MoveNext())
    Console.WriteLine(iter.Current);

По моему опыту, IEnumerator редко используется в распространенных сценариях из-за его более многословного синтаксиса и немного сбивающей с толку семантики (по крайней мере, для меня; например, MoveNext() также возвращает значение, которое имя вообще не предлагает).

Вариант использования для IEnumerator

Я использовал только IEnumerator, в частности (немного более низкого уровня) библиотеки и платформы, где я предоставлял интерфейсы IEnumerable. Одним из примеров является библиотека обработки потока данных, которая предоставляла серии объектов в цикле foreach хотя данные за сценой собирались с использованием различных файловых потоков и сериализаций.

Код клиента

foreach(var item in feed.GetItems())
    Console.WriteLine(item);

Библиотека

IEnumerable GetItems() {
    return new FeedIterator(_fileNames)
}

class FeedIterator: IEnumerable {
    IEnumerator GetEnumerator() {
        return new FeedExplicitIterator(_stream);
    }
}

class FeedExplicitIterator: IEnumerator {
    DataItem _current;

    bool MoveNext() {
        _current = ReadMoreFromStream();
        return _current != null;           
    }

    DataItem Current() {
        return _current;   
    }
}

Ответ 9

Реализация IEnumerable по существу означает, что объект может быть переименован. Это не обязательно означает, что это массив, поскольку есть определенные списки, которые не могут быть проиндексированы, но вы можете их перечислить.

IEnumerator - это фактический объект, используемый для выполнения итераций. Он управляет переходом от одного объекта к следующему в списке.

В большинстве случаев IEnumerable и IEnumerator используются прозрачно как часть цикла foreach.

Ответ 10

Различия между IEnumerable и IEnumerator:

  • IEnumerable использует IEnumerator для внутреннего использования.
  • IEnumerable не знает, какой элемент/объект выполняется.
  • Всякий раз, когда мы передаем IEnumerator другой функции, он знает текущую позицию элемента/объекта.
  • Всякий раз, когда мы передаем коллекцию IEnumerable другой функции, она не знает текущую позицию элемента/объекта (не знает, какой элемент выполняется)

    IEnumerable имеет один метод GetEnumerator()

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

IEnumerator имеет одно свойство, называемое Current, и два метода, Reset() и MoveNext() (которые полезны для определения текущей позиции элемента в списке).

public interface IEnumerator
{
     object Current { get; }
     bool MoveNext();
     void Reset();
}

Ответ 11

Понимание шаблона Iterator будет полезно для вас. Я рекомендую прочитать то же самое.

Итерационный шаблон

На высоком уровне шаблон итератора может использоваться для обеспечения стандартного способа итерации через коллекции любого типа. У нас есть 3 участника шаблона итератора, фактический сбор (клиент), агрегатор и итератор. Агрегат - это интерфейс/абстрактный класс, который имеет метод, который возвращает итератор. Итератор - это интерфейс/абстрактный класс, который имеет методы, позволяющие нам выполнять итерацию по коллекции.

Чтобы реализовать шаблон, нам сначала нужно реализовать итератор для создания конкретного, который может перебирать соответствующую коллекцию (клиент) Затем сборщик (клиент) реализует агрегатор для возврата экземпляра вышеупомянутого итератора.

Вот диаграмма UML шаблон итератора

Итак, в основном в С#, IEnumerable - абстрактный агрегат, а IEnumerator - абстрактный Iterator. IEnumerable имеет единственный метод GetEnumerator, который отвечает за создание экземпляра IEnumerator требуемого типа. Коллекции, подобные спискам, реализуют IEnumerable.

Пример. Предположим, что у нас есть метод getPermutations(inputString), который возвращает все перестановки строки и что метод возвращает экземпляр IEnumerable<string>

Чтобы подсчитать количество перестановок, мы могли бы сделать что-то вроде ниже.

 int count = 0;
        var permutations = perm.getPermutations(inputString);
        foreach (string permutation in permutations)
        {
            count++;
        }

Компилятор С# более или менее преобразует приведенное выше значение в

using (var permutationIterator = perm.getPermutations(input).GetEnumerator())
        {
            while (permutationIterator.MoveNext())
            {
                count++;
            }
        }

Если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь спрашивать.

Ответ 12

IEnumerable - это блок, содержащий Ienumerator. IEnumerable является базовым интерфейсом для всех коллекций. Цикл foreach может работать, если коллекция реализует IEnumerable. В приведенном ниже коде объясняется, как создать собственный перечислитель. Давайте сначала определим наш класс, из которого мы собираемся сделать коллекцию.

public class Customer
{
    public String Name { get; set; }
    public String City { get; set; }
    public long Mobile { get; set; }
    public double Amount { get; set; }
}

Теперь мы определим класс, который будет действовать как коллекция для нашего класса Customer. Обратите внимание, что он реализует интерфейс IEnumerable. Так что нам нужно реализовать метод GetEnumerator. Это вернет наш пользовательский перечислитель.

public class CustomerList : IEnumerable
{
    Customer[] customers = new Customer[4];
    public CustomerList()
    {
        customers[0] = new Customer { Name = "Bijay Thapa", City = "LA", Mobile = 9841639665, Amount = 89.45 };
        customers[1] = new Customer { Name = "Jack", City = "NYC", Mobile = 9175869002, Amount = 426.00 };
        customers[2] = new Customer { Name = "Anil min", City = "Kathmandu", Mobile = 9173694005, Amount = 5896.20 };
        customers[3] = new Customer { Name = "Jim sin", City = "Delhi", Mobile = 64214556002, Amount = 596.20 };
    }

    public int Count()
    {
        return customers.Count();
    }
    public Customer this[int index]
    {
        get
        {
            return customers[index];
        }
    }
    public IEnumerator GetEnumerator()
    {
        return customers.GetEnumerator(); // we can do this but we are going to make our own Enumerator
        return new CustomerEnumerator(this);
    }
}

Теперь мы собираемся создать наш собственный Enumerator следующим образом. Итак, мы должны реализовать метод MoveNext.

 public class CustomerEnumerator : IEnumerator
    {
        CustomerList coll;
        Customer CurrentCustomer;
        int currentIndex;
        public CustomerEnumerator(CustomerList customerList)
        {
            coll = customerList;
            currentIndex = -1;
        }

        public object Current => CurrentCustomer;

        public bool MoveNext()
        {
            if ((currentIndex++) >= coll.Count() - 1)
                return false;
            else
                CurrentCustomer = coll[currentIndex];
            return true;
        }

        public void Reset()
        {
            // we dont have to implement this method.
        }
    }

Теперь мы можем использовать цикл foreach над нашей коллекцией, как показано ниже;

    class EnumeratorExample
    {
        static void Main(String[] args)
        {

            CustomerList custList = new CustomerList();
            foreach (Customer cust in custList)
            {
                Console.WriteLine("Customer Name:"+cust.Name + " City Name:" + cust.City + " Mobile Number:" + cust.Amount);
            }
            Console.Read();

        }
    }

Ответ 13

A Незначительный вклад.

Как многие из них объясняют "когда использовать" и "использовать с foreach". Я подумал о добавлении здесь параметра States Difference здесь, как задано в вопросе о различии между IEnumerable IEnumerator.

Я создал приведенный ниже пример кода на основе ниже описанных потоков обсуждения.

IEnumerable, IEnumerator vs foreach, когда использовать то, что В чем разница между IEnumerator и IEnumerable?

Перечислитель сохраняет состояние (позицию итерации) между вызовами функций, в то время как итерации с другой стороны Enumerable этого не делают.

Вот пример с комментариями для понимания.

Эксперты, пожалуйста, добавьте/исправьте меня.

static void EnumerableVsEnumeratorStateTest()
{
    IList<int> numList = new List<int>();

    numList.Add(1);
    numList.Add(2);
    numList.Add(3);
    numList.Add(4);
    numList.Add(5);
    numList.Add(6);

    Console.WriteLine("Using Enumerator - Remembers the state");
    IterateFrom1to3(numList.GetEnumerator());

    Console.WriteLine("Using Enumerable - Does not Remembers the state");
    IterateFrom1to3Eb(numList);

    Console.WriteLine("Using Enumerable - 2nd functions start from the item 1 in the collection");
}

static void IterateFrom1to3(IEnumerator<int> numColl)
{
    while (numColl.MoveNext())
    {
        Console.WriteLine(numColl.Current.ToString());

        if (numColl.Current > 3)
        {
            // This method called 3 times for 3 items (4,5,6) in the collection. 
            // It remembers the state and displays the continued values.
            IterateFrom3to6(numColl);
        }
    }
}

static void IterateFrom3to6(IEnumerator<int> numColl)
{
    while (numColl.MoveNext())
    {
        Console.WriteLine(numColl.Current.ToString());
    }
}

static void IterateFrom1to3Eb(IEnumerable<int> numColl)
{
    foreach (int num in numColl)
    {
        Console.WriteLine(num.ToString());

        if (num>= 5)
        {
            // The below method invokes for the last 2 items.
            //Since it doesnot persists the state it will displays entire collection 2 times.
            IterateFrom3to6Eb(numColl);
        }
    }
}

static void IterateFrom3to6Eb(IEnumerable<int> numColl)
{
    Console.WriteLine();
    foreach (int num in numColl)
    {
        Console.WriteLine(num.ToString());
    }
}

Ответ 14

Я заметил эти различия:

а. Мы перебираем список по-разному, foreach можно использовать для IEnumerable и while loop для IEnumerator.

В. IEnumerator может помнить текущий индекс при переходе от одного метода к другому (он начинает работать с текущим индексом), но IEnumerable не может запомнить индекс и reset индекс для начала. Подробнее в этом видео https://www.youtube.com/watch?v=jd3yUjGc9M0

Ответ 15

IEnumerable и IEnumerator оба являются интерфейсами в С#.

IEnumerable - это интерфейс, определяющий единственный метод GetEnumerator() который возвращает интерфейс IEnumerator.

Это работает для доступа только для чтения к коллекции, которая реализует, что IEnumerable может использоваться с оператором foreach.

IEnumerator имеет два метода, MoveNext и Reset. Он также имеет свойство под названием Current.

Ниже показана реализация IEnumerable и IEnumerator.

Ответ 16

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Enudemo
{

    class Person
    {
        string name = "";
        int roll;

        public Person(string name, int roll)
        {
            this.name = name;
            this.roll = roll;
        }

        public override string ToString()
        {
            return string.Format("Name : " + name + "\t Roll : " + roll);
        }

    }


    class Demo : IEnumerable
    {
        ArrayList list1 = new ArrayList();

        public Demo()
        {
            list1.Add(new Person("Shahriar", 332));
            list1.Add(new Person("Sujon", 333));
            list1.Add(new Person("Sumona", 334));
            list1.Add(new Person("Shakil", 335));
            list1.Add(new Person("Shruti", 336));
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
           return list1.GetEnumerator();
        }
    }



    class Program
    {
        static void Main(string[] args)
        {
            Demo d = new Demo();  // Notice here. it is simple object but for 
                                //IEnumerator you can get the collection data

            foreach (Person X in d)
            {
                Console.WriteLine(X);
            }

            Console.ReadKey();
        }
    }
}
/*
Output : 

Name : Shahriar  Roll : 332
Name : Sujon     Roll : 333
Name : Sumona    Roll : 334
Name : Shakil    Roll : 335
Name : Shruti    Roll : 336
  */

Ответ 17

using System;
using System.Collections;


namespace IEnumerableDemo
{
    class Demo
    {
        int[] a = { 1, 2, 3, 4, 5 };

        public IEnumerator GetEnumerator()
        {
            return a.GetEnumerator();
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            Demo d = new Demo();    // Here we can use object for array data
                                      //by IEnumerable
            foreach (int X in d)
            {
                Console.WriteLine(X);
            }

            Console.ReadKey();
        }
    }
}

/* Output:
 1
 2
 3
 4
 5
*/

Ответ 18

using System;
using System.Collections;


namespace IEnumerableDemo
{
    class Demo
    {
        int[] a = { 1, 2, 3, 4, 5 };

        public IEnumerator GetEnumerator()
        {
            foreach (int X in a)      // or you can use this version
            {                           // it will produce same output
                yield return X;
            }            
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Demo d = new Demo();

            foreach (int X in d)
            {
                Console.WriteLine(X);
            }
            Console.ReadKey();
        }
    }
}

/* Output:
 1
 2
 3
 4
 5
*/