Você pode escolher uma resposta aceita diferente, uma vez que aquela que você selecionou não representa realmente a resposta correta.
George Stocker
Respostas:
162
Na verdade, estritamente falando, tudo que você precisa usar foreaché um GetEnumerator()método público que retorna algo com um bool MoveNext()método e uma ? Current {get;}propriedade. No entanto, o significado mais comum disso é "algo que implementa IEnumerable/ IEnumerable<T>, retornando um IEnumerator/ IEnumerator<T>.
Por implicação, isso inclui qualquer coisa que implementa ICollection/ ICollection<T>, como qualquer coisa como Collection<T>, List<T>, matrizes ( T[]), etc. Assim, qualquer "recolha de dados" padrão geralmente apoiar foreach.
Para provar o primeiro ponto, o seguinte funciona perfeitamente:
using System;
classFoo {
publicint Current { get; privateset; }
privateint step;
publicboolMoveNext() {
if (step >= 5) returnfalse;
Current = step++;
returntrue;
}
}
classBar {
public Foo GetEnumerator() { returnnew Foo(); }
}
staticclassProgram {
staticvoidMain() {
Bar bar = new Bar();
foreach (int item in bar) {
Console.WriteLine(item);
}
}
}
Como funciona?
Um loop foreach como foreach(int i in obj) {...}meio que equivale a:
var tmp = obj.GetEnumerator();
int i; // up to C# 4.0while(tmp.MoveNext()) {
int i; // C# 5.0
i = tmp.Current;
{...} // your code
}
No entanto, existem variações. Por exemplo, se o enumerador (tmp) for compatível IDisposable, ele também será usado (semelhante a using).
Observe a diferença na colocação da declaração " int i" dentro (C # 5.0) vs. fora (até C # 4.0) do loop. É importante se você usar iem um método anônimo / lambda dentro de seu bloco de código. Mas essa é outra história ;-p
1 para ir em profundidade. Normalmente não vou tão a fundo para uma questão que pode ser uma questão de 'iniciante', pois pareceria opressora para o novo programador.
George Stocker
Verdade, Gortok - então continuei com o material sobre listas / matrizes / etc.
Marc Gravell
Seria bom mencionar a conversão implícita de tempo de execução na variável de loop - pode produzir exceções de incompatibilidade de tipo.
Daniel Earwicker
3
Não se esqueça: ao usar um array com foreach, o compilador cria um simples for-loop(você pode ver isso ao trabalhar com IL).
Felix K.
1
@Marc Gravell: OK, legal! Eu editei a postagem para deixar mais claro - pelo menos para mim. Afinal, o posicionamento não é importante apenas no C # 5.0, é sempre importante, apenas que ele mudou. Espero que você não se importe.
A foreachinstrução repete um grupo de instruções incorporadas para cada elemento em uma matriz ou coleção de objetos . A foreachinstrução é usada para iterar pela coleção para obter as informações desejadas, mas não deve ser usada para alterar o conteúdo da coleção para evitar efeitos colaterais imprevisíveis. (ênfase minha)
Portanto, se você tiver uma matriz, poderá usar a instrução foreach para iterar pela matriz, assim:
curiosamente, de acordo com o MSDN ( msdn.microsoft.com/en-us/library/9yb8xew9(VS.80).aspx ), os tipos de objetos não precisam implementar IEnumerable. Qualquer tipo que defina GetEnumerator, MoveNext, Reset e Current da maneira correta funcionará. Estranho, hein?
Sean Reilly
Arrumado. Eu não sabia disso. :-)
George Stocker
4
De acordo com a postagem do blog Duck Notation , a digitação duck é usada.
É importante observar que "O tipo do elemento de coleção deve ser conversível para o tipo de identificador". Isso às vezes não pode ser verificado em tempo de compilação e pode gerar uma exceção de tempo de execução se o tipo de instância não puder ser atribuído ao tipo de referência.
Isso gerará uma exceção de tempo de execução se houver um não-Apple na cesta de frutas, como uma laranja.
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)
Isso filtra com segurança a lista apenas para as maçãs usando Enumerable.OfType
List<int> numbers = new List<int>();
numbers.Add(5);
numbers.Add(15);
numbers.Add(25);
numbers.Add(35);
Console.WriteLine("You are added total number: {0}",numbers.Count);
foreach (int number in numbers)
{
Console.WriteLine("Your adding Number are: {0}", number);
}
Respostas:
Na verdade, estritamente falando, tudo que você precisa usar
foreach
é umGetEnumerator()
método público que retorna algo com umbool MoveNext()
método e uma? Current {get;}
propriedade. No entanto, o significado mais comum disso é "algo que implementaIEnumerable
/IEnumerable<T>
, retornando umIEnumerator
/IEnumerator<T>
.Por implicação, isso inclui qualquer coisa que implementa
ICollection
/ICollection<T>
, como qualquer coisa comoCollection<T>
,List<T>
, matrizes (T[]
), etc. Assim, qualquer "recolha de dados" padrão geralmente apoiarforeach
.Para provar o primeiro ponto, o seguinte funciona perfeitamente:
using System; class Foo { public int Current { get; private set; } private int step; public bool MoveNext() { if (step >= 5) return false; Current = step++; return true; } } class Bar { public Foo GetEnumerator() { return new Foo(); } } static class Program { static void Main() { Bar bar = new Bar(); foreach (int item in bar) { Console.WriteLine(item); } } }
Como funciona?
Um loop foreach como
foreach(int i in obj) {...}
meio que equivale a:var tmp = obj.GetEnumerator(); int i; // up to C# 4.0 while(tmp.MoveNext()) { int i; // C# 5.0 i = tmp.Current; {...} // your code }
No entanto, existem variações. Por exemplo, se o enumerador (tmp) for compatível
IDisposable
, ele também será usado (semelhante ausing
).Observe a diferença na colocação da declaração "
int i
" dentro (C # 5.0) vs. fora (até C # 4.0) do loop. É importante se você usari
em um método anônimo / lambda dentro de seu bloco de código. Mas essa é outra história ;-pfonte
for-loop
(você pode ver isso ao trabalhar com IL).Do MSDN :
Portanto, se você tiver uma matriz, poderá usar a instrução foreach para iterar pela matriz, assim:
int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 }; foreach (int i in fibarray) { System.Console.WriteLine(i); }
Você também pode usá-lo para iterar por meio de uma
List<T>
coleção, assim:List<string> list = new List<string>(); foreach (string item in list) { Console.WriteLine(item); }
fonte
De acordo com a postagem do blog Duck Notation , a digitação duck é usada.
fonte
Aqui estão os documentos: Artigo principal com matrizes com objetos de coleção
É importante observar que "O tipo do elemento de coleção deve ser conversível para o tipo de identificador". Isso às vezes não pode ser verificado em tempo de compilação e pode gerar uma exceção de tempo de execução se o tipo de instância não puder ser atribuído ao tipo de referência.
Isso gerará uma exceção de tempo de execução se houver um não-Apple na cesta de frutas, como uma laranja.
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() }; foreach(Apple a in fruitBasket)
Isso filtra com segurança a lista apenas para as maçãs usando Enumerable.OfType
foreach(Apple a in fruitBasket.OfType<Apple>() )
fonte
IList<ListItem> illi = new List<ListItem>(); ListItem li = null; foreach (HroCategory value in listddlsubcategory) { listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id); li = new ListItem(); li.Text = value.Description; li.Value = value.Id.ToString(); illi.Add(li); IList<ListItem> newilli = new List<ListItem>(); newilli = SubCatagoryFunction(listddlsubcategoryext, "-->"); foreach (ListItem c in newilli) { illi.Add(c); } }
fonte
Informações úteis sobre este assunto também podem ser encontradas no MSDN . Tirando a essência desse artigo:
A palavra-chave foreach enumera uma coleção, executando a instrução incorporada uma vez para cada elemento da coleção:
foreach (var item in collection) { Console.WriteLine(item.ToString()); }
O compilador traduz o loop foreach mostrado no exemplo acima em algo semelhante a esta construção:
IEnumerator<int> enumerator = collection.GetEnumerator(); while (enumerator.MoveNext()) { var item = enumerator.Current; Console.WriteLine(item.ToString()); }
fonte
você pode tentar isso ...
List<int> numbers = new List<int>(); numbers.Add(5); numbers.Add(15); numbers.Add(25); numbers.Add(35); Console.WriteLine("You are added total number: {0}",numbers.Count); foreach (int number in numbers) { Console.WriteLine("Your adding Number are: {0}", number); }
fonte