Como funciona o foreach quando looping através de resultados de função?
Pergunta
Suponha que eu tenho o seguinte código:
foreach(string str in someObj.GetMyStrings())
{
// do some stuff
}
Will someObj.GetMyStrings()
ser chamado em cada iteração do loop? Seria melhor para fazer o seguinte em vez disso:
List<string> myStrings = someObj.GetMyStrings();
foreach(string str in myStrings)
{
// do some stuff
}
?
Solução
A função é chamado apenas uma vez, para retornar uma IEnumerator<T>
; depois disso, o método MoveNext()
ea propriedade Current
são usados ??para percorrer os resultados:
foreach (Foo f in GetFoos())
{
// Do stuff
}
é um tanto equivalente a:
using (IEnumerator<Foo> iterator = GetFoos().GetEnumerator())
{
while (iterator.MoveNext())
{
Foo f = iterator.Current;
// Do stuff
}
}
. Note que o iterador está disposto no final - isto é particularmente importante para a eliminação recursos do iterador blocos, p.ex.:
public IEnumerable<string> GetLines(string file)
{
using (TextReader reader = File.OpenText(file))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
No código acima, você realmente deseja que o arquivo a ser fechado quando você termina a iteração, e os implementos compilador IDisposable
astuciosamente para fazer esse trabalho.
Outras dicas
Não .. a função será chamada uma vez para obter o IEnumerable .. e então não será repetido chamada para MoveNext e Current.
GetMyStrings () retuns um objeto do tipo IEnumerable. O tempo de execução sabe como lidar com isso. Ele chama IEnumerable.GetEnumerator () e depois no objeto enumerador chama MoveNext () e atual.
Apenas para completar a pergunta fora no caso de você cair em um "tudo por são os mesmos";
para (int x = 0; X