Eficiencia
La palabra clave yield
crea efectivamente una enumeración perezosa sobre los elementos de la colección que pueden ser mucho más eficientes. Por ejemplo, si su bucle foreach
itera solo sobre los primeros 5 elementos de 1 millón de artículos, entonces eso es todo yield
devuelve, y no creó una colección de 1 millón de artículos internamente primero. Del mismo modo, deseará usar yield
con IEnumerable<T>
de los valores de retorno en sus propios escenarios de programación para lograr las mismas eficiencias.
Ejemplo de eficiencia obtenida en un escenario determinado
No es un método de iterador, el uso ineficiente potencial de una gran colección,
(La colección intermedia se construye con muchos elementos)
// 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.
Versión de iterador, eficiente
(No se crea una colección intermedia)
// 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.
Simplifique algunos escenarios de programación
En otro caso, hace que algunos tipos de clasificación y fusión de listas sean más fáciles de programar porque usted simplemente yield
artículos nuevamente en el orden deseado en lugar de clasificarlos en una colección intermedia e intercambiarlos allí. Hay muchos de esos escenarios.
Un solo ejemplo es la combinación de dos listas:
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;
}
Este método devuelve una lista contigua de elementos, de hecho, una combinación sin necesidad de recopilación intermedia.
Más información
La palabra clave yield
solo se puede usar en el contexto de un método iterador (que tiene un tipo de retorno de IEnumerable
, IEnumerator
, IEnumerable<T>
o IEnumerator<T>
.) y existe una relación especial con% código%. Los iteradores son métodos especiales. La documentación de rendimiento de MSDN y documentación del iterador contiene mucha información interesante y una explicación de los conceptos. Asegúrese de correlacionarlo con la palabra clave foreach
por leyendo sobre esto también, para complementar su comprensión de los iteradores.
Para aprender cómo los iteradores logran su eficiencia, el secreto está en el código IL generado por el compilador de C #. La IL generada para un método de iterador difiere drásticamente de la generada para un método regular (no iterador). Este artículo (¿Qué genera realmente la palabra clave de rendimiento?) proporciona ese tipo de información.