Efficienza
La parola chiave yield
crea effettivamente un'enumerazione pigra sugli elementi di raccolta che può essere molto più efficiente. Ad esempio, se il tuo ciclo foreach
esegue iterazioni solo sui primi 5 elementi di 1 milione di articoli, questo è tutto yield
restituito e non hai prima creato una raccolta di 1 milione di articoli internamente. Allo stesso modo, vorrai utilizzare yield
con IEnumerable<T>
valori di ritorno nei tuoi scenari di programmazione per ottenere le stesse efficienze.
Esempio di efficienza acquisita in un determinato scenario
Non è un metodo iteratore, un potenziale uso inefficiente di una grande raccolta,
(la raccolta intermedia è costruita con molti elementi)
// Method returns all million items before anything can loop over them.
List<object> GetAllItems() {
List<object> millionCustomers;
database.LoadMillionCustomerRecords(millionCustomers);
return millionCustomers;
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in GetAllItems()) {
num++;
if (num == 5)
break;
}
// Note: One million items returned, but only 5 used.
Versione Iterator, efficiente
(Nessuna raccolta intermedia è stata creata)
// Yields items one at a time as the caller's foreach loop requests them
IEnumerable<object> IterateOverItems() {
for (int i; i < database.Customers.Count(); ++i)
yield return database.Customers[i];
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in IterateOverItems()) {
num++;
if (num == 5)
break;
}
// Note: Only 5 items were yielded and used out of the million.
Semplifica alcuni scenari di programmazione
In un altro caso, rende più facili da programmare alcuni tipi di ordinamento e fusione di elenchi, perché solo yield
elementi indietro nell'ordine desiderato anziché ordinarli in una raccolta intermedia e scambiarli lì. Ci sono molti di questi scenari.
Un solo esempio è la fusione di due elenchi:
IEnumerable<object> EfficientMerge(List<object> list1, List<object> list2) {
foreach(var o in list1)
yield return o;
foreach(var o in list2)
yield return o;
}
Questo metodo restituisce un elenco contiguo di elementi, in pratica un'unione senza alcuna raccolta intermedia necessaria.
Altre informazioni
La parola chiave yield
può essere utilizzata solo nel contesto di un metodo iteratore (con un tipo di ritorno di IEnumerable
, IEnumerator
, IEnumerable<T>
o IEnumerator<T>
.) e c'è una relazione speciale con% codice%. Gli iteratori sono metodi speciali. documentazione di rendimento MSDN e la documentazione di iterator contiene molte informazioni interessanti e spiegazioni sui concetti. Assicurati di correlarlo con la parola chiave foreach
di leggendo anche su questo, per integrare la tua comprensione degli iteratori.
Per sapere come gli iteratori raggiungono la loro efficienza, il segreto è nel codice IL generato dal compilatore C #. L'IL generato per un metodo iteratore differisce drasticamente da quello generato per un metodo regolare (non iteratore). Questo articolo (Cosa fa la parola chiave di rendimento Really Generate?) fornisce quel tipo di intuizione.