Foreach Cache IEnumerable?

Supponendo che SomeMethod abbia firma

 public IEnumerable SomeMethod(); 

c’è qualche differenza tra

 foreach (T tmp in SomeMethod()) { ... } 

e

 IEnumerable result = SomeMethod(); foreach (T tmp in result) { ... } 

In altre parole, i risultati di SomeMethod saranno memorizzati nella prima istruzione o saranno valutati a ogni iterazione?

Supponendo che tu stia parlando di C #.

foreach traduce in qualcosa di simile a questo:

 var enumerable = SomeMethod(); // Or whatever is passed to foreach var enumerator = enumerable.GetEnumerator(); while (enumerator.MoveNext()) { ... } 

Quindi, dato che enumerable è necessario solo una volta, ci sarà una sola chiamata a SomeMethod anche se viene inserita direttamente nell’istruzione foreach .

Un enumeratore è generalmente un diverso tipo di object da un elenco. Tipicamente un enumeratore conterrà un riferimento a un object enumerabile, insieme ad alcune informazioni su dove si trova nel processo di enumerazione. Lo scopo di un object enumerabile non è in realtà quello di fornire una sequenza di elementi, ma piuttosto di fornire un enumeratore che a sua volta fornirà la sequenza.

In entrambi vb.net e C #, il costrutto foreach funziona chiamando un metodo GetEnumerator una volta sull’object e afferrando l’object restituito, chiamando ripetutamente MoveNext e Current sull’object restituito da GetEnumerator e infine, se quell’object implementa Dispose, chiamando Smaltigli. Né C # né vb.net memorizzano nella cache l’object enumerabile, ma nessuno di essi deve utilizzare l’object per alcuno scopo dopo aver chiamato GetEnumerator su di esso una volta. Entrambe le lingue sono valide per l’enumeratore, ma nessuno dei due fornisce alcun modo per fare altro con le chiamate implicite a MoveNext, Current e Dispose.