Alguém pode me explicar IEnumerable e IEnumerator? [fechadas]

272

Alguém pode me explicar IEnumerable e IEnumerator?

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

prodev42
fonte
55
Este é o pior confusão de nomenclatura desde Java e JavaScript
Matthew Bloqueio
@MatthewLock, você pode explicar o que você quer dizer?
David Klempfner 4/10/19

Respostas:

275

por exemplo, quando usá-lo no foreach?

Você não usa IEnumerable"over" foreach. Execução IEnumerabletorna o uso foreach possível .

Quando você escreve um código como:

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

é funcionalmente equivalente a escrever:

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

Por "funcionalmente equivalente", quero dizer que é na verdade o que o compilador transforma o código. Você não pode usar foreachem bazneste exemplo , a menos baz implementos IEnumerable.

IEnumerablesignifica que bazimplementa o método

IEnumerator GetEnumerator()

O IEnumeratorobjeto que esse método retorna deve implementar os métodos

bool MoveNext()

e

Object Current()

O primeiro método avança para o próximo objeto no IEnumerableobjeto que criou o enumerador, retornandofalse se estiver pronto, e o segundo retorna o objeto atual.

Qualquer coisa no .Net que você possa iterar sobre os implementos IEnumerable. Se você está construindo sua própria classe e ela ainda não herda de uma classe implementada IEnumerable, você pode utilizá-la em foreachinstruções implementando IEnumerable(e criando uma classe enumeradora que seu novo GetEnumeratormétodo retornará).

Robert Rossney
fonte
15
Acho que quando o pôster original dizia "over foreach", ele queria dizer "quando devo chamar GetEnumerator () / MoveNext () explicitamente, em vez de usar um loop foreach". Pelo que vale a pena.
Mqp 17/02/09
6
Ah, acho que você está certo. Bem, a resposta está implícita no meu post: não importa, já que é o que o compilador faz de qualquer maneira. Faça o que é mais fácil, ou seja, use foreach.
23333 Robert Rossney
12
Essa resposta não conta a história toda. Objetos enumeráveis ​​não precisam implementar IEnumerable; eles só precisam ter um método GetEnumerator que retorne uma instância de um tipo que, por sua vez, possua um bool MoveNext()método e uma Currentpropriedade de qualquer tipo. Essa abordagem de "digitação de pato" foi implementada no C # 1.0 como uma maneira de evitar o boxe ao enumerar coleções de tipo de valor.
Phoog
3
Com a exaltação de cima e trabalhando através de Workthrough: Implementing IEnumerable of (T), você tem fontes greate.
2014
4
Isso é como um C ++ iterator?
Matt G
161

As interfaces IEnumerable e IEnumerator

Para começar a examinar o processo de implementação de interfaces .NET existentes, vejamos primeiro a função de IEnumerable e IEnumerator. Lembre-se de que o C # oferece suporte a uma palavra-chave denominada foreach que 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 apenas os tipos de matriz podem fazer uso dessa construção, a verdade é que qualquer tipo que suporte um método chamado GetEnumerator () pode ser avaliado pela construção foreach. Para 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 iterar nos subitens do objeto Garage usando a construção foreach, assim 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, o compilador informa que a classe Garage não implementa um método chamado GetEnumerator (). Esse método é formalizado pela interface IEnumerable, que se encontra à espreita no espaço de nomes System.Collections. Classes ou estruturas que suportam esse comportamento anunciam que podem expor subitens contidos ao chamador (neste exemplo, a própria palavra-chave foreach). Aqui está a definição dessa interface .NET padrão:

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

Como você pode ver, o método GetEnumerator () retorna uma referência para outra interface chamada System.Collections.IEnumerator. Essa interface fornece a infraestrutura para permitir que o chamador atravesse os objetos internos contidos no contêiner compatível com IEnumerable:

// 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ê deseja atualizar o tipo de Garagem para suportar essas interfaces, pode seguir o longo caminho e implementar cada método manualmente. Embora você tenha a liberdade de fornecer versões personalizadas de GetEnumerator (), MoveNext (), Current e Reset (), existe 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 ao System.Array da seguinte maneira:

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 atualizar seu tipo de Garagem, você pode usá-lo com segurança na construção C # foreach. Além disso, como o método GetEnumerator () foi definido publicamente, o usuário do objeto também pode interagir 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ê preferir ocultar a funcionalidade de IEnumerable do nível do objeto, basta usar a implementação explícita da interface:

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

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

Adaptado do Pro C # 5.0 e do .NET 4.5 Framework

Disse Roohullah Allem
fonte
1
Resposta fantástica, obrigado! Eu tenho uma pergunta, no entanto. No primeiro exemplo, você faz um loop sobre a matriz usando foreach, mas não pode fazê-lo no segundo exemplo. Isso ocorre porque a matriz está em uma classe ou porque contém objetos?
Caleb Palmquist
Obrigado pela ótima explicação. Minha única pergunta é por que não apenas ter um método Garageque receba carArray? Dessa forma, você não precisa se implementar GetEnumerator, pois Arrayjá faz isso. Exemploforeach(Car c in carLot.getCars()) { ... }
Nick Rolando
63

Implementar IEnumerable significa que sua classe retorna um objeto IEnumerator:

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

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

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

    public bool MoveNext()...

    public object Current...
}

Essa é a diferença de qualquer maneira.

testemunho
fonte
1
Bom, isso explica (juntamente com as outras postagens) como converter sua classe em uma que você pode usar "foreach" para iterar sobre seu conteúdo.
Contango
54

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

Primeiro uma explicação sem código, depois a adicionarei.

Digamos que você esteja administrando uma companhia aérea. E em cada avião você deseja saber informações sobre os passageiros que voam no avião. Basicamente, você deseja "atravessar" o avião. Em outras palavras, você deseja poder começar no banco da frente e depois seguir em direção à parte traseira do avião, perguntando aos passageiros algumas informações: quem eles são, de onde são etc. Um avião só pode fazer isso , se for:

  1. contável e
  2. se tiver um contador.

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

Se for uma sobrecarga de informações, tudo o que você precisa saber é que você pode fazer algumas perguntas a cada passageiro no avião, começando pelo primeiro e indo até o último.

O que significa contável?

Se uma companhia aérea é "contável", isso significa que DEVE haver um comissário de bordo presente no avião, cuja única tarefa é contar - e esse comissário de bordo DEVE contar de uma maneira muito específica:

  1. O contador / comissário de bordo DEVE começar antes do primeiro passageiro (na frente de todos onde demonstram segurança, como colocar o colete salva-vidas etc.).
  2. Ele (ela é a comissária de bordo) DEVE "avançar" pelo corredor até o primeiro assento.
  3. Ele / ela deve então registrar: (i) quem é a pessoa no assento e (ii) sua localização atual no corredor.

Procedimentos de contagem

O capitão da companhia aérea deseja um relatório sobre todos os passageiros, como e quando forem investigados ou contados. Assim, depois de falar com a pessoa no primeiro assento, o comissário de bordo / contador se reporta ao capitão e, quando o relatório é entregue, o contador se lembra de sua posição exata no corredor e continua contando exatamente onde deixou fora.

Dessa maneira, o capitão sempre pode ter informações sobre a pessoa atual sendo investigada. Dessa forma, se ele descobrir que esse indivíduo gosta do Manchester City, poderá dar tratamento preferencial a esse passageiro etc.

  • O balcão continua indo até ele chegar ao fim do avião.

Vamos amarrar isso com os IEnumerables

  • Um enumerável é apenas uma coleção de passageiros em um avião. A Lei da Aviação Civil - estas são basicamente as regras que todos os IEnumerables devem seguir. Sempre que o atendente da companhia aérea vai ao capitão com as informações do passageiro, estamos basicamente 'cedendo' o passageiro ao capitão. O capitão pode basicamente fazer o que quiser com o passageiro - exceto reorganizar os passageiros no avião. Nesse caso, eles recebem tratamento preferencial se seguirem o 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 tiver um contador . E o contador deve (basicamente): (i) lembrar seu lugar ( estado ), (ii) ser capaz de avançar , (iii) e saber sobre o atual pessoa quem está lidando.

Enumerável é apenas uma palavra chique para "contável". Em outras palavras, um enumerável permite que você 'enumere' (ou seja, conte).

BKSpurgeon
fonte
23

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

Portanto, quando sua classe implementa IEnumerable, você está dizendo que pode chamar um método (GetEnumerator) e obter um novo objeto retornado (um IEnumerator) que pode ser usado em um loop como foreach.

DavGarcia
fonte
18

A implementação de IEnumerable permite obter um IEnumerator para uma lista.

O IEnumerator permite o acesso seqüencial de cada estilo aos itens da lista, usando a palavra-chave yield.

Antes de cada implementação (no Java 1.4, por exemplo), a maneira de iterar uma lista era obter um enumerador da lista e solicitar o item "próximo" na lista, desde que o valor retornado como o próximo item não é nulo. O Foreach simplesmente faz isso implicitamente como um recurso de linguagem, da mesma maneira que lock () implementa a classe Monitor nos bastidores.

Espero que cada trabalho funcione em listas porque eles implementam IEnumerable.

Neil Barnwell
fonte
se é uma lista, por que não posso usar o foreach?
Prodev42 17/02/09
O .net duck digita a instrução foreach, mas IEnumerable / IEnumerable <T> é a maneira apropriada de dizer que sua classe pode ser enumerada.
user7116
15
  • Um objeto implementando IEnumerable permite que outras pessoas visitem cada um de seus itens (por um enumerador) .
  • Um objeto que implementa IEnumerator é a realização da iteração. Está circulando sobre um objeto enumerável.

Pense em objetos inumeráveis ​​como listas, pilhas, árvores.

Lieven Keersmaekers
fonte
12

IEnumerable e IEnumerator (e seus equivalentes genéricos IEnumerable <T> e IEnumerator <T>) são interfaces básicas de implementações do iterador nas coleções do .Net Framework Class Libray .

IEnumerable é a interface mais comum que você veria na maioria do código existente. Ele permite o loop foreach, geradores (think yield ) e, devido à sua pequena interface, é usado para criar abstrações restritas. IEnumerable depende de IEnumerator .

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

IEnumerable

IEnumerable é uma interface padrão que permite a iteração sobre coleções que a suporta (na verdade, todos os tipos de coleção que eu consigo pensar hoje implementam IEnumerable ). O suporte ao compilador permite recursos de idioma como foreach. Em termos gerais, ele permite a implementação implícita do iterador .

Loop foreach

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

Eu acho que o foreachloop é uma das principais razões para o uso de interfaces IEnumerable . foreachpossui uma sintaxe muito sucinta e muito fácil de entender em comparação com o estilo C clássico para loops, onde você precisa verificar as várias variáveis ​​para ver o que estava fazendo.

yield Palavra-chave

Provavelmente, um recurso menos conhecido é que IEnumerable também habilita geradores em C # com o uso de yield returne yield breakinstruções.

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

Abstrações

Outro cenário comum na prática é usar IEnumerable para fornecer abstrações minimalistas. Por ser uma interface minúscula e somente leitura, é recomendável expor suas coleções como IEnumerable (em vez de Lista, por exemplo). Dessa forma, você é livre para alterar sua implementação sem quebrar o código do seu cliente (altere List para uma LinkedList, por exemplo).

Peguei vocês

Um comportamento a ser observado é que, nas implementações de streaming (por exemplo, recuperando dados linha por linha de um banco de dados, em vez de carregar todos os resultados na memória primeiro), você não pode repetir a coleção mais de uma vez. Isso contrasta com as coleções na memória, como a Lista , na qual é possível iterar várias vezes sem problemas. O ReSharper, por exemplo, possui uma inspeção de código para Possível enumeração múltipla de IEnumerable .

IEnumerator

O IEnumerator, por outro lado, é a interface dos bastidores que faz o IEnumerble-foreach-magic funcionar. A rigor, ele permite iteradores explícitos.

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

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

Caso de uso para IEnumerator

Eu só usei o IEnumerator em particular bibliotecas e estruturas (nível um pouco mais baixo) onde fornecia interfaces IEnumerable . Um exemplo é uma biblioteca de processamento de fluxo de dados que forneceu uma série de objetos em um foreachloop, embora os dados dos bastidores tenham sido coletados usando vários fluxos de arquivos e serializações.

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;   
    }
}
ziya
fonte
9

Implementar IEnumerablesignifica essencialmente que o objeto pode ser iterado. Isso não significa necessariamente que é uma matriz, pois existem certas listas que não podem ser indexadas, mas você pode enumerá-las.

IEnumeratoré o objeto real usado para executar as iterações. Controla a movimentação de um objeto para o próximo na lista.

Na maioria das vezes, IEnumerable& IEnumeratorsão usados ​​de forma transparente como parte de um foreachloop.

Dan Herbert
fonte
6

Diferenças entre IEnumerable e IEnumerator:

  • IEnumerable usa IEnumerator internamente.
  • IEnumerable não sabe qual item / objeto está executando.
  • Sempre que passamos o IEnumerator para outra função, ele conhece a posição atual do item / objeto.
  • Sempre que passamos uma coleção IEnumerable para outra função, ela não sabe a posição atual do item / objeto (não sabe qual item está sendo executado)

    IEnumerable tem um método GetEnumerator ()

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

IEnumerator tem uma propriedade chamada Current e dois métodos, Reset () e MoveNext () (que é útil para conhecer a posição atual de um item em uma lista).

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

IEnumerable é uma caixa que contém o Ienumerator. IEnumerable é a interface base para todas as coleções. O loop foreach pode operar se a coleção implementar IEnumerable. No código abaixo, explica a etapa de ter nosso próprio enumerador. Vamos primeiro definir nossa classe da qual vamos 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 definiremos a classe que atuará como uma coleção para a nossa classe Customer. Observe que ele está implementando a interface IEnumerable. Para que tenhamos de implementar o método GetEnumerator. Isso retornará nosso enumerador personalizado.

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 nosso próprio enumerador personalizado da seguinte maneira. Portanto, 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 o loop foreach sobre 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();

        }
    }
Amir
fonte
4

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

Padrão Iterador

Em um nível alto, o padrão do iterador pode ser usado para fornecer uma maneira padrão de iterar através de coleções de qualquer tipo. Temos 3 participantes no padrão do iterador, a coleção real (cliente), o agregador e o iterador. O agregado é uma classe de interface / resumo que possui um método que retorna um iterador. Iterator é uma interface / classe abstrata que possui métodos que permitem iterar através de uma coleção.

Para implementar o padrão, primeiro precisamos implementar um iterador para produzir um concreto que possa iterar sobre a coleção em questão (cliente). Em seguida, a coleção (cliente) implementa o agregador para retornar uma instância do iterador acima.

Aqui está o diagrama UML Padrão Iterador

Então, basicamente em c #, IEnumerable é o agregado abstrato e IEnumerator é o iterador abstrato. IEnumerable possui um único método GetEnumerator, responsável por criar uma instância de IEnumerator do tipo desejado. Coleções como Lists implementam o IEnumerable.

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

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

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

O compilador c # converte mais ou menos o acima para

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

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

lalatnayak
fonte
2

Uma contribuição menor.

Como muitos deles explicam sobre 'quando usar' e 'usar com foreach'. Pensei em adicionar outra diferença de estados aqui, conforme solicitado em questão, sobre a diferença entre IEnumerable e IEnumerator.

Criei o exemplo de código abaixo com base nos tópicos de discussão abaixo.

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

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

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

Especialistas por favor me adicione / corrija.

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

Eu notei essas diferenças:

R. Nós iteramos a lista de maneira diferente, foreach pode ser usado para IEnumerable e loop while para IEnumerator.

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

RotatingWheel
fonte
1

IEnumerablee IEnumeratorambos são interfaces em c #.

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

Isso funciona para acesso somente leitura a uma coleção que implementa que IEnumerablepode ser usada com uma foreachinstrução

IEnumeratortem dois métodos MoveNexte Reset. Ele também tem uma propriedade chamadaCurrent .

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

Jihed Jaoidi
fonte
0
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
  */
Md Shahriar
fonte