How to: Acessar uma classe de coleção com foreach (guia de programação C#)
O exemplo de código a seguir ilustra como escrever uma classe de coleção não genéricas que pode ser usada com foreach. O exemplo define uma classe de tokenizer de seqüência de caracteres.
Observação |
---|
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 oferece suporte a IEnumerable<T>, consulte How to: Criar um iterador Bloco para uma genérica Lista (guia de programação C#). |
No exemplo, o código a seguir segmento usa o 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 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 a 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.
*/
No 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 GetEnumerator, MoveNext, Reset, e Current membros, ele funcionará com foreach. Omitir as interfaces tem a vantagem de permitindo que você defina o tipo de retorno para Current isto é 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 a instrução, como mostra o 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 é mais interoperável com o foreach instruções, ou instruções de equivalentes de outros idiomas da tempo de execução comum do idioma.
Consulte também
Referência
Collection Classes (C# Programming Guide)
Conceitos
Outros recursos
Histórico de alterações
Date |
History |
Motivo |
---|---|---|
Março de 2011 |
Revisado para aumentar a clareza. |
Aprimoramento de informações. |