Pergunta

Alguém pode explicar IEnumerable e IEnumerator para mim?

Por exemplo, quando usá-lo sobre foreach? qual é a diferença entre IEnumerable e IEnumerator? Por que precisamos usá-lo?

Foi útil?

Solução

Por exemplo, quando usá-lo sobre foreach?

Você não use IEnumerable "over" foreach. Implementação IEnumerable torna o uso foreach possível .

Quando você escrever código como:

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

é funcionalmente equivalente à escrita:

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

Por "funcionalmente equivalente", quero dizer que é realmente o que o compilador transforma o código em. Você não pode usar foreach em baz neste exemplo menos implementos baz IEnumerable.

meios IEnumerable que implementos baz o método

IEnumerator GetEnumerator()

O objeto IEnumerator que este método retorna deve implementar os métodos

bool MoveNext()

e

Object Current()

Os primeiros avanços de método para o próximo objeto no objeto IEnumerable que criou o enumerador, retornando false se for feito, eo segundo retorna o objeto atual.

Qualquer coisa na Net que você pode iterar sobre implementos IEnumerable. Se você está construindo sua própria classe, e ele já não herdar de uma classe que implementa IEnumerable, você pode fazer o seu utilizável classe em declarações foreach através da implementação de IEnumerable (e criando uma classe enumerador que seu novo método GetEnumerator voltará) .

Outras dicas

O IEnumerable e IEnumerator Interfaces

Para começar a examinar o processo de implementação de interfaces .NET existentes, vamos primeiro olhar para o papel de IEnumerable e IEnumerator. Lembre-se que C # suporta uma palavra-chave chamada foreach que lhe permite iterar sobre o conteúdo de qualquer tipo de matriz:

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

Embora possa parecer que os únicos tipos de matriz pode fazer uso dessa construção, a verdade da questão é qualquer tipo de suporte de um método chamado GetEnumerator () pode ser avaliada pelo foreach construct.To ilustrar, siga-me!

Suponha que tenhamos uma classe 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);
   }
}

Idealmente, seria conveniente para interagir sobre subitens do objeto Garagem usando o foreach construo, tal como uma matriz de valores de dados:

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

Infelizmente, as informa compilador que a classe Garage não implementa um método chamado GetEnumerator (). Este método é formalizada pela interface IEnumerable, que se encontra escondido no interior do espaço de nomes System.Collections. Classes ou estruturas que suportam este comportamento anunciar que eles são capazes de expor contido subitens para o chamador (neste exemplo, o foreach própria palavra-chave). Aqui está a definição desta interface padrão NET:

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

Como você pode ver, o GetEnumerator () método retorna uma referência para outra interface chamada System.Collections.IEnumerator. Essa interface fornece a infra-estrutura para permitir que o chamador para atravessar os objetos internos contidos pelo recipiente IEnumerable compatível com:

// 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.
}

Se você quiser atualizar o tipo de garagem para apoiar essas interfaces, você poderia tomar o longo caminho e implementar cada método manualmente. Enquanto você está certamente livre para oferecer versões personalizadas de GetEnumerator (), MoveNext (), atual, e Reset (), não há uma maneira mais simples. Como o tipo System.Array (assim como muitas outras classes de coleção) já implementa IEnumerable e IEnumerator, você pode simplesmente delegar a solicitação para o System.Array como segue:

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

Depois de ter actualizado o seu tipo de garagem, você pode usar com segurança o tipo de dentro da construção C # foreach. Além disso, dado que o método GetEnumerator () tem sido definida publicamente, o utilizador podia também objecto interagem com o tipo 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);

No entanto, se você prefere esconder a funcionalidade de IEnumerable do nível do objeto, basta fazer usar de implementação de interface explícita:

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

Ao fazer isso, o usuário objeto ocasional não vai encontrar o método do Garage GetEnumerator (), enquanto a construção foreach irá obter a interface em segundo plano quando necessário.

Pro C # 5.0 e o .NET Framework 4.5

Implementar IEnumerable significa sua classe retorna um objeto IEnumerator:

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

Implementar IEnumerator significa sua classe retorna os métodos e propriedades para a iteração:

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

    public bool MoveNext()...

    public object Current...
}

Essa é a diferença de qualquer maneira.

Explicação via Analogia + Código Passo a passo

Primeiro uma explicação, sem código, então eu vou adicioná-lo mais tarde.

Vamos dizer que você está executando uma companhia aérea. E em cada plano que você quer saber informações sobre os passageiros que voam no avião. Basicamente, você quer ser capaz de "travessia" do avião. Em outras palavras, você quer ser capaz de começar no banco da frente, e, em seguida, trabalhar o seu caminho para a parte traseira do avião, pedindo aos passageiros algumas informações: quem são, de onde eles são etc. Um avião só pode fazer isso , se é:

  1. contável, e
  2. Se tiver um marcador.

Por que esses requisitos? Porque é isso que a interface requer.

Se esta é a sobrecarga de informações, tudo que você precisa saber é que você quer ser capaz de pedir a cada passageiro no plano algumas perguntas, a partir da primeira e fazer o seu caminho até o fim.

O que significa contável?

Se uma companhia aérea é "contáveis", isso significa que deve haver uma aeromoça presente no avião, que é único trabalho é para contar - e este aeromoça deve contar de uma maneira muito específica:

  1. O atendente contador / vôo deve começar antes do primeiro passageiro (na frente de todo mundo onde eles demonstração de segurança, como colocar o colete salva-vidas etc).
  2. Ele / ela (ou seja, a aeromoça) deve "passar ao lado" até o corredor para o primeiro lugar.
  3. Ele / ela é, em seguida, recorde:. (I) que a pessoa está no banco, e (ii) a sua localização actual no corredor

procedimentos de contagem

O capitão da companhia aérea quer um relatório sobre cada passageiro como e quando eles são investigados ou contados. Então, depois de falar com a pessoa no primeiro assento, o vôo-atendimento / balcão em seguida, informa ao capitão, e quando o relatório é dado, o contador lembra de seu / sua posição exata no corredor e continua contando exatamente onde ele / ela deixou off.

Desta forma, o capitão é sempre capaz de ter informações sobre a pessoa atual que está sendo investigado. Dessa forma, se ele descobre que essa pessoa gosta Manchester City, em seguida, ele pode dar esse passageiro tratamento preferencial etc.

  • O contador continua indo até que ele chegue ao final do avião.

Vamos empate isso com os IEnumerables

  • Um enumeráveis ??é apenas uma coleção de passageiros de um avião. A Lei de Aviação Civil - estes são, basicamente, as regras que todos os IEnumerables deve seguir. Toda vez atendente da companhia aérea vai para o capitão com a informação passeger, que são basicamente 'ceder' o passageiro para o capitão. O capitão pode basicamente fazer o que quiser com o passageiro - exceto reorganizar os passageiros no avião. Neste caso, eles recebem tratamento preferencial se eles seguirem Manchester City (ugh!)

    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)
    

Resumo

Em outras palavras, algo é contável se ele tem um contador . E contra must (basicamente): (i) lembrar seu lugar ( Estado ), (ii) ser capaz de move próxima , (iii) e saber sobre o atual pessoa que ele está lidando.

Enumerable é apenas uma palavra chique para a "contabilidade". Em outras palavras, um enumeráveis ??permite 'enumerar' (contagem ou seja).

IEnumerable implementos GetEnumerator. Quando chamado, esse método retornará um IEnumerator que implementa MoveNext, Reset e atual.

Assim, quando seus implementos classe IEnumerable, você está dizendo que você pode chamar um método (GetEnumerator) e obter um novo objeto retornado (um IEnumerator) você pode usar em um loop, como foreach.

Implementar IEnumerable permite-lhe obter um IEnumerator para uma lista.

IEnumerator permite estilo foreach acesso sequencial para os itens na lista, utilizando a palavra-chave de rendimento.

Antes da implementação foreach (em Java 1.4, por exemplo), a forma de interagir uma lista era conseguir um enumerador da lista, em seguida, pedir-lo para a "próxima" item na lista, enquanto o valor retornado como o próximo item não é nulo. Foreach simplesmente faz isso implicitamente como um recurso de linguagem, da mesma forma que lock () implementa a classe Monitor de bastidores.

Espero obras foreach em listas porque eles implementar IEnumerable.

  • Um objeto implementando IEnumerable permite que outras pessoas para visitar cada um dos seus itens (por um recenseador) .
  • Um objeto implementando IEnumerator é a fazer a iteração. É looping sobre um objeto enumerável.

Pense em objetos enumeráveis ??como de listas, pilhas, árvores.

IEnumerable e IEnumerator (e seus equivalentes genéricos IEnumerable e IEnumerator ) são interfaces de base do iterator implementações em .Net Framework Classe coleções Libray .

IEnumerable é a interface mais comum que você veria na maioria do código lá fora. Ele permite que o loop foreach, geradores (pense rendimento ) e por causa de sua interface minúsculo, ele é usado para criar abstrações apertados. IEnumerable depende IEnumerator .

IEnumerator , por outro lado, fornece uma interface um pouco menor nível de iteração. É referido como o iterador explícito que dá o programador mais controle sobre o iteração ciclo.

IEnumerable

IEnumerable é uma interface padrão que permite a iteração sobre coleções que o suporta (na verdade, todos os tipos de coleção que eu posso pensar de implementos hoje IEnumerable ). Compilador de suporte permite que recursos de linguagem como foreach. Em termos gerais, que permite que esta implícita implementação iterador .

foreach loop

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

Eu acho circuito foreach é uma das principais razões para a utilização de IEnumerable interfaces. foreach tem uma sintaxe muito sucinto e muito fácil de entender em relação ao clássico C estilo para loops onde você precisa verificar as diversas variáveis ??para ver o que estava fazendo.

render palavra-chave

Provavelmente um recurso menos conhecido é que IEnumerable também permite que geradores em C # com o uso de yield return e yield break declarações.

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

Abstrações

Outro cenário comum na prática está usando IEnumerable para fornecer abstrações minimalistas. Porque é um minúsculo e só de leitura interface, que são incentivados a expor suas coleções como IEnumerable (em vez de List , por exemplo). Dessa forma, você é livre para mudar sua implementação sem quebrar (Lista mudança para um LinkedList , por exemplo) o código do seu cliente.

Gotcha

Um comportamento para estar ciente de que em streaming implementações (por exemplo, a recuperação de linha de dados por linha a partir de um banco de dados, em vez de carregar todos os resultados em memória primeiro) você não pode iterar sobre a coleção mais de uma vez. Isso está em contraste com coleções na memória como List , onde você pode interagir várias vezes sem problemas. ReSharper, por exemplo, tem uma inspeção de código para Possível enumeração múltiplo de IEnumerable .

IEnumerator

IEnumerator, por outro lado, é o por trás das cenas de interface que torna IEnumerble-foreach-magic trabalho. Estritamente falando, ele permite iterators explícitas.

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

Em minha experiência IEnumerator é raramente usado em cenários comuns, devido à sua mais detalhado sintaxe e um pouco confuso semântica (pelo menos para mim; por exemplo, MoveNext () retorna um valor assim, que o nome não sugere em tudo).

Use caso para IEnumerator

I usado apenas IEnumerator em particular bibliotecas (nível ligeiramente inferior) e os quadros onde estava proporcionando IEnumerable interfaces. Um exemplo é uma biblioteca de processamento de fluxo de dados which série fornecidos de objetos em um loop foreach mesmo que por trás dos dados cenas foram obtidos utilizando vários fluxos de arquivo e serializações.

O código do cliente

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

Biblioteca

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;   
    }
}

IEnumerable Implementar significa essencialmente que o objeto pode ser iterada. Isso não significa necessariamente que ele é um array, pois há determinadas listas que não podem ser indexados, mas você pode enumerá-los.

IEnumerator é o objeto real usado para executar as iterações. Ele controla se deslocam de um objeto para o próximo na lista.

A maioria das vezes, IEnumerable & IEnumerator são usados ??de forma transparente, como parte de um ciclo foreach. |

As diferenças entre IEnumerable e IEnumerator:

  • IEnumerable usa IEnumerator internamente.
  • não sabe IEnumerable qual item / objeto está em execução.
  • Sempre que passamos IEnumerator para outra função, ele sabe a posição atual do item / objeto.
  • Sempre que passamos coleção IEnumerable para outra função, não sabe a posição atual do item / objeto (não sabe qual item a sua execução)

    IEnumerable tem um método GetEnumerator ()

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

IEnumerator tem uma corrente de propriedade e dois métodos Repor e MoveNext (que é útil para saber a posição atual de um item em uma lista).

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

Uma compreensão do padrão Iterator será útil para você. Eu recomendo a leitura do mesmo.

Iterator Padrão

Em um nível alto o padrão iterador pode ser usado para fornecer uma maneira padrão de iteração através de coleções de qualquer tipo. Temos 3 participantes no padrão iterator, a coleção real (cliente), o agregador e o iterador. O agregado é um interface de classe / sumário que tem um método que retorna uma iteração. Iterator é uma interface de classe / abstrata que tem métodos permitindo-nos para percorrer uma coleção.

A fim de implementar o padrão que primeiro precisa implementar um iterador para produzir um concreto que pode iterar sobre a coleção preocupado (cliente) Em seguida, a coleção (cliente) implementa o agregador para retornar uma instância do acima iterador.

Aqui está o diagrama UML Iterator Padrão

Então, basicamente em c #, IEnumerable é o agregado abstrato e IEnumerator é o resumo Iterator. IEnumerable tem um único GetEnumerator método que é responsável pela criação de uma instância de IEnumerator do tipo desejado. Coleções como listas de implementar o IEnumerable.

Exemplo. Vamos supor que temos um getPermutations(inputString) método que retorna todas as permutações de uma corda e que o método retorna uma instância de IEnumerable<string>

Para contar o número de permutações que poderíamos fazer algo como o abaixo.

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

O c # compilador mais ou menos converte os acima para

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

Se você tiver alguma dúvida, por favor, não hesite em perguntar.

IEnumerable é uma caixa que contém IEnumerator. IEnumerable é a interface base para todas as coleções. loop foreach pode funcionar se os instrumentos de coleta de IEnumerable. No código abaixo que explica o passo de ter o nosso próprio Enumerator. Vamos primeiro definir nossa classe da qual estamos indo fazer a coleção.

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

Agora vamos definir a classe que irá funcionar como uma coleção para a nossa classe Cliente. Aviso que está a implementar a interface IEnumerable. Assim que temos de implementar o GetEnumerator método. Isso retornará nosso costume Enumerator.

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

Agora, vamos criar a nossa própria Enumerator personalizado como acompanhamento. Então, temos que implementar o método 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.
        }
    }

Agora podemos usar loop foreach sobre a nossa coleção como abaixo;

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

        }
    }

A Minor contribuição.

Como muitos deles explicar sobre 'quando usar' e 'uso com foreach'. Pensei em adicionar Outra Estados Diferença aqui tal como solicitado na pergunta sobre a diferença entre ambos IEnumerable um IEnumerator.

Eu criei o código abaixo amostra com base no abaixo tópicos de discussão.

IEnumerable, IEnumerator vs foreach, quando usar o Qual é a diferença entre IEnumerator e IEnumerable?

Enumerator preserva o estado (posição iteração) entre chamadas de função, enquanto iterações outro lado Enumerable não.

Aqui está o exemplo testado com comentários de entender.

Especialistas Por favor, adicione / me corrigir.

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

Tenho notado estas diferenças:

A. Nós iterar a lista de forma diferente, foreach pode ser usado para IEnumerable e enquanto loop para IEnumerator.

B. IEnumerator pode lembrar o índice atual quando passamos de um método para outro (ele começar a trabalhar com índice atual), mas IEnumerable não me lembro o índice e redefinir o índice para começar. Mais neste vídeo https://www.youtube.com/watch?v=jd3yUjGc9M0

IEnumerable e IEnumerator ambos são interfaces em C #.

IEnumerable é uma interface que define um único método GetEnumerator() que retorna uma interface IEnumerator.

Isso funciona para acesso somente leitura a uma coleção que implementa que IEnumerable pode ser usado com uma declaração foreach.

IEnumerator tem dois métodos, MoveNext e Reset. Ele também tem uma propriedade chamada Current.

Os seguir mostra a implementação de IEnumerable e IEnumerator.

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
  */
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top