Como acessar uma classe de coleção com foreach (Guia de Programação em C#)
O exemplo de código a seguir ilustra como escrever uma classe de coleção não genérico que pode ser usada com foreach. O exemplo define uma classe de tokenizer de seqüência de caracteres.
Dica
Este exemplo representa a prática recomendada somente quando você não pode usar uma classe de coleção genérica.Para obter um exemplo de como implementar uma classe de coleção genérica de tipo seguro que ofereça suporte a IEnumerable, consulte Iteradores (C# e Visual Basic).
No exemplo, o código a seguir segmento usa a Tokens classe para quebrar a frase "Esta é uma frase de exemplo." em tokens usando ' ' e '-' como separadores. O código, em seguida, exibe esses tokens usando um foreach instrução.
Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});
// Display the tokens.
foreach (string item in f)
{
System.Console.WriteLine(item);
}
Exemplo
Internamente, o Tokens classe usa uma matriz para armazenar os tokens. Como as matrizes implementam IEnumerator e IEnumerable, o exemplo de código poderia ter usado a métodos de enumeração da matriz (GetEnumerator, MoveNext, Reset, e Current) em vez de defini-los na Tokens classe. As definições de método são incluídas no exemplo para esclarecer como são definidas e o que cada um oferece.
using System.Collections;
// Declare the Tokens class. The class implements the IEnumerable interface.
public class Tokens : IEnumerable
{
private string[] elements;
Tokens(string source, char[] delimiters)
{
// The constructor parses the string argument into tokens.
elements = source.Split(delimiters);
}
// The IEnumerable interface requires implementation of method GetEnumerator.
public IEnumerator GetEnumerator()
{
return new TokenEnumerator(this);
}
// Declare an inner class that implements the IEnumerator interface.
private class TokenEnumerator : IEnumerator
{
private int position = -1;
private Tokens t;
public TokenEnumerator(Tokens t)
{
this.t = t;
}
// The IEnumerator interface requires a MoveNext method.
public bool MoveNext()
{
if (position < t.elements.Length - 1)
{
position++;
return true;
}
else
{
return false;
}
}
// The IEnumerator interface requires a Reset method.
public void Reset()
{
position = -1;
}
// The IEnumerator interface requires a Current method.
public object Current
{
get
{
return t.elements[position];
}
}
}
// Test the Tokens class.
static void Main()
{
// Create a Tokens instance.
Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});
// Display the tokens.
foreach (string item in f)
{
System.Console.WriteLine(item);
}
}
}
/* Output:
This
is
a
sample
sentence.
*/
Em C#, não é necessário para implementar uma classe de coleção IEnumerable e IEnumerator para ser compatível com foreach. Se a classe tem o necessário GetEnumerator, MoveNext, Reset, e Current membros, ele funcionará com foreach. Omitir as interfaces tem a vantagem de permitindo que você defina um tipo de retorno para Current que é mais específico do que Object. Isso fornece segurança de tipos.
Por exemplo, altere as seguintes linhas no exemplo anterior.
// Change the Tokens class so that it no longer implements IEnumerable.
public class Tokens
{
// . . .
// Change the return type for the GetEnumerator method.
public TokenEnumerator GetEnumerator()
{ }
// Change TokenEnumerator so that it no longer implements IEnumerator.
public class TokenEnumerator
{
// . . .
// Change the return type of method Current to string.
public string Current
{ }
}
}
Porque Current retorna uma seqüência de caracteres, o compilador pode detectar quando um tipo incompatível é usado em um foreach instrução, como mostrado no código a seguir.
// Error: Cannot convert type string to int.
foreach (int item in f)
A desvantagem de omissão IEnumerable e IEnumerator é que a classe de coleção não é interoperável com o foreach declarações ou instruções equivalentes, de outros idiomas de runtime de linguagem comum.
Consulte também
Referência
Matrizes (Guia de Programação em C#)