Eficiência
A palavra-chave yield
cria efetivamente uma enumeração lenta sobre itens de coleção que pode ser muito mais eficiente. Por exemplo, se o seu loop foreach
percorrer apenas os primeiros 5 itens de 1 milhão de itens, então todos os yield
retornam, e você não criou uma coleção de 1 milhão de itens internamente primeiro. Da mesma forma, você desejará usar yield
com IEnumerable<T>
valores de retorno em seus próprios cenários de programação para obter as mesmas eficiências.
Exemplo de eficiência obtida em um determinado cenário
Não é um método iterador, potencial uso ineficiente de uma grande coleção,
(a coleção Intermediária é construída com muitos itens)
// 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.
Versão do iterador, eficiente em (Nenhuma coleção intermediária é criada)
// 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 alguns cenários de programação
Em outro caso, é mais fácil programar alguns tipos de classificação e mesclagem de listas, porque você apenas yield
itens retornam na ordem desejada, em vez de classificá-los em uma coleção intermediária e trocá-los lá. Existem muitos desses cenários.
Apenas um exemplo é a fusão de duas 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 retorna uma lista contígua de itens, efetivamente uma mesclagem sem necessidade de coleta intermediária.
Mais informações
A palavra-chave yield
só pode ser usada no contexto de um método iterador (com um tipo de retorno de IEnumerable
, IEnumerator
, IEnumerable<T>
ou IEnumerator<T>
.) e há uma relação especial com% código%. Iteradores são métodos especiais. A documentação de rendimento do MSDN e documentação do iterador contém muita informação interessante e explicação dos conceitos. Certifique-se de correlacioná-lo com a palavra-chave foreach
da lendo sobre isso também, para complementar sua compreensão de iteradores.
Para aprender sobre como os iteradores alcançam sua eficiência, o segredo está no código IL gerado pelo compilador C #. O IL gerado para um método iterador difere drasticamente daquele gerado para um método regular (não-iterador). Este artigo (O que faz a palavra-chave de rendimento?) Really Generate?) fornece esse tipo de percepção.