Pergunta

Esta questão já tem uma resposta aqui:

Eu estava passando por IEnumerable e IEnumerator, mas não conseguiu obter um ponto clearly..if temos foreach, então por que precisamos deste duas interfaces? Existe algum cenário onde temos que usar interfaces.If sim, então alguém pode explicar com um exemplo. Todas as sugestões e comentários são bem-vindos. Obrigado.

Foi útil?

Solução

foreach usos as interfaces em muitos casos. Você precisa as interfaces se você quiser implementar uma sequência que foreach pode então usar. (Blocos Iterator geralmente fazem esta tarefa implementação muito simples embora.)

No entanto, apenas ocasionalmente , pode ser útil para usar os iteradores diretamente. Um bom exemplo é quando tentando "casar-se" duas seqüências diferentes. Por exemplo, suponha que você recebe duas seqüências - um dos nomes, uma das idades, e que pretende imprimir os dois juntos. Você pode escrever:

static void PrintNamesAndAges(IEnumerable<string> names, IEnumerable<int> ages)
{
    using (IEnumerator<int> ageIterator = ages.GetEnumerator())
    {
        foreach (string name in names)
        {
            if (!ageIterator.MoveNext())
            {
                throw new ArgumentException("Not enough ages");
            }
            Console.WriteLine("{0} is {1} years old", name, ageIterator.Current);
        }
        if (ageIterator.MoveNext())
        {
            throw new ArgumentException("Not enough names");
        }

    }
}

Da mesma forma, pode ser útil usar o iterator se você quiser tratar (digamos) o primeiro item diferente para o resto:

public T Max<T>(IEnumerable<T> items)
{
    Comparer<T> comparer = Comparer<T>.Default;

    using (IEnumerator<T> iterator = items.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            throw new InvalidOperationException("No elements");
        }
        T currentMax = iterator.Current;

        // Now we've got an initial value, loop over the rest
        while (iterator.MoveNext())
        {
            T candidate = iterator.Current;
            if (comparer.Compare(candidate, currentMax) > 0)
            {
                currentMax = candidate;
            }
        }
        return currentMax;
    }
}

Agora, se você estiver interessado na diferença entre IEnumerator<T> e IEnumerable<T>, você pode querer pensar nisso em termos de banco de dados: pensar em IEnumerable<T> como uma tabela, e IEnumerator<T> como um cursor. Você pode pedir uma mesa para lhe dar um novo cursor, e você pode ter vários cursores sobre a mesma tabela ao mesmo tempo.

Pode demorar um pouco para realmente grok esta diferença, mas apenas lembrar que uma lista (ou matriz, ou qualquer outro) não tem qualquer conceito de "onde você está na lista", mas um iterador sobre essa lista / array / whatever faz tem aquele pedaço de estado é útil.

Outras dicas

O que disse Jon.

  • IEnumerable ou IEnumerable<T>: Com a implementação deste um objeto estados que ele pode lhe dar um iterador que você pode usar para atravessar sobre a seqüência / coleta / set
  • IEnumerator ou IEnumerator<T>: se você chamar o método GetEnumerator definido na interface anterior, você recebe um objeto iterador como uma referência IEnumerator. Isso permite que você chamar MoveNext () e obter o objeto atual.
  • foreach: é um C # construção / fachada em um sentido em que você não precisa saber como ele funciona sob o capô. Ele fica internamente o iterador e chama os métodos adequados para você se concentrar no que você quer fazer com cada item (o conteúdo do bloco foreach). Na maioria das vezes, você só precisa foreach a menos que você esteja implementando seu próprio tipo ou costume iteração, caso em que você precisa para conhecer os primeiros 2 interfaces.

Tenha em mente que você não Have para implementar IEnumerator e varients do mesmo para uso foreach - IIRC, tudo o que precisa é um método GetEnumerator () que retorna um objeto que tem um MoveNext () método retornando um bool, e uma propriedade Current retornar um objeto. Você não precisa usar IEnumerator e IEnumerable, embora geralmente é uma idéia muito boa para fazer isso. Consulte aqui para mais informações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top