Wydajność
Słowo yield
kluczowe skutecznie tworzy leniwe wyliczenie ponad elementami kolekcji, które mogą być znacznie bardziej wydajne. Na przykład, jeśli twoja foreach
pętla dokonuje iteracji tylko pierwszych 5 elementów z 1 miliona przedmiotów, to wszystko to yield
zwraca, a najpierw nie zbudowałeś kolekcji 1 miliona przedmiotów. Podobnie będzie chciał skorzystać yield
z IEnumerable<T>
wartości zwracanych własnymi scenariuszami programowania, aby osiągnąć te same korzyści.
Przykład wydajności uzyskanej w określonym scenariuszu
Nie jest to metoda iteracyjna, potencjalnie nieefektywne użycie dużej kolekcji
(kolekcja pośrednia jest zbudowana z dużą ilością przedmiotów)
// 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.
Wersja Iterator, wydajna
(nie jest budowana kolekcja pośrednia)
// 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.
Uprość niektóre scenariusze programowania
W innym przypadku ułatwia to programowanie sortowania i scalania list, ponieważ po prostu yield
elementy z powrotem w pożądanej kolejności zamiast sortować je do kolekcji pośredniej i zamieniać je tam. Istnieje wiele takich scenariuszy.
Jednym z przykładów jest połączenie dwóch list:
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;
}
Ta metoda daje jedną ciągłą listę elementów, co skutecznie łączy się bez pośredniej kolekcji.
Więcej informacji
yield
Kluczowe może być stosowany tylko w kontekście metody iteracyjnej (o typ zwrotnego IEnumerable
, IEnumerator
, IEnumerable<T>
, i IEnumerator<T>
.) I nie jest szczególny stosunek foreach
. Iteratory to specjalne metody. Dokumentacja wydajności MSDN i dokumentacja iteratora zawiera wiele interesujących informacji i objaśnień pojęć. Pamiętaj, aby skorelować go z foreach
kluczowych czytając o nim też uzupełnić swoją wiedzę iteratorów.
Aby dowiedzieć się, w jaki sposób iteratory osiągają swoją wydajność, sekret znajduje się w kodzie IL wygenerowanym przez kompilator C #. IL wygenerowana dla metody iteracyjnej różni się drastycznie od generowanej dla zwykłej metody (nie iteracyjnej). Ten artykuł (co naprawdę generuje słowo kluczowe Yield?) Zawiera tego rodzaju informacje.