Como o foreach funciona quando faz o loop através dos resultados da function?

Suponha que eu tenha o seguinte código:

foreach(string str in someObj.GetMyStrings()) { // do some stuff } 

Será que someObj.GetMyStrings() será chamado em cada iteração do loop? Seria melhor fazer o seguinte em vez disso:

 List myStrings = someObj.GetMyStrings(); foreach(string str in myStrings) { // do some stuff } 

?

A function é chamada apenas uma vez, para retornar um IEnumerator ; depois disso, o método MoveNext() e a propriedade Current são usados ​​para percorrer os resultados:

 foreach (Foo f in GetFoos()) { // Do stuff } 

é um pouco equivalente a:

 using (IEnumerator iterator = GetFoos().GetEnumerator()) { while (iterator.MoveNext()) { Foo f = iterator.Current; // Do stuff } } 

Observe que o iterador é descartado no final – isso é particularmente importante para descartar resources dos blocos do iterador, por exemplo:

 public IEnumerable 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 seja fechado quando concluir a iteração, e o compilador implementa IDisposable astuciosamente para fazer esse trabalho.

Não .. a function será chamada uma vez para obter o IEnumerable .. e, em seguida, haverá chamada repetida para MoveNext e Current.

GetMyStrings () retunde um object do tipo IEnumerable. O tempo de execução sabe como lidar com isso. Ele chama IEnumerable.GetEnumerator () e, em seguida, nesse object de enumerador chama MoveNext () e atual.

Apenas para arredondar a questão para o caso de você cair em um “tudo é o mesmo”; para (int x = 0; x