yield (odwołanie w C#)
Użycie słowa kluczowego yield w instrukcji powoduje wskazanie metody, operatora lub metody dostępu get, w których to słowo kluczowe występuje jako iterator.Użycie słowa kluczowego yield w celu zdefiniowania iteratora eliminuje konieczność jawnego użycia dodatkowej klasy (klasy przechowującej stan wyliczenia, na przykład IEnumerator) podczas implementacji wzorców IEnumerable i IEnumerator dla niestandardowej kolekcji typów.
W poniższym przykładzie pokazano dwa rodzaje instrukcji yield.
yield return <expression>;
yield break;
Uwagi
Instrukcja yield return umożliwia jednokrotne zwrócenie każdego elementu.
Metoda iteratora jest używana za pomocą instrukcji foreach lub zapytania w języku LINQ.W każdej iteracji pętli foreach jest wywoływana metoda iteratora.Po osiągnięciu instrukcji yield return w metodzie iteratora jest zwracana wartość parametru expression, a bieżąca lokalizacja w kodzie jest zachowywana.Wykonanie jest uruchamiane ponownie z tej lokalizacji przy następnym wywołaniu funkcji iteratora.
Iterację można zakończyć za pomocą instrukcji yield break.
Aby uzyskać więcej informacji dotyczących iteratorów, zobacz Iteratory (C# i Visual Basic).
Metody iteratorów i pobranie akcesora
Deklaracja iteratora musi spełniać następujące wymagania:
Zwracanym typem musi być IEnumerable, IEnumerable, IEnumerator lub IEnumerator.
Typ yield iteratora zwracającego interfejs IEnumerable lub IEnumerator to object. Jeśli iterator zwraca interfejs IEnumerable lub IEnumerator, musi być określona niejawna konwersja typu z instrukcji yield return na parametr typu ogólnego.
Instrukcji yield return i yield break nie można używać w metodach mających następujące cechy:
Metody anonimowe.Aby uzyskać więcej informacji, zobacz Metody anonimowe (Przewodnik programowania w języku C#).
Metody, które zawierają bloki ze słowem kluczowym unsafe.Aby uzyskać więcej informacji, zobacz unsafe (odwołanie w C#).
Obsługa wyjątków
Instrukcja yield return nie może znajdować się w bloku try-catch.Instrukcja yield return może znajdować się w bloku try instrukcji try-finally.
Instrukcja yield break może znajdować się w bloku try lub bloku catch, ale nie w bloku finally.
Jeśli treść pętli foreach (poza metodą iteratora) zgłasza wyjątek, jest wykonywany blok finally w metodzie iteratora.
Realizacja techniczna
Poniższy kod zwraca interfejs IEnumerable<string> z metody iteratora, a następnie wykonuje iterację na jego elementach.
IEnumerable<string> elements = MyIteratorMethod();
foreach (string element in elements)
{
…
}
Wywołanie metody MyIteratorMethod nie powoduje wykonania treści metody.Zamiast tego to wywołanie zwraca interfejs IEnumerable<string> do zmiennej elements.
Podczas iteracji pętli foreach metoda MoveNext jest wywoływana dla zmiennej elements.To wywołanie wykonuje treść metody MyIteratorMethod, aż zostanie osiągnięta następna instrukcja yield return.Wyrażenie zwracane przez instrukcję yield return określa nie tylko wartość zmiennej element przeznaczonej do użycia w treści pętli, ale określa również właściwość Current elementów, która jest interfejsem IEnumerable<string>.
Przy poszczególnych kolejnych iteracjach pętli foreach wykonywanie treści iteratora jest kontynuowane od miejsca, w którym zostało przerwane, i jest zatrzymywane ponownie po osiągnięciu instrukcji yield return.Wykonywanie pętli foreach kończy się, gdy zostanie osiągnięty koniec metody iteratora lub instrukcja yield break.
Przykład
W poniższym przykładzie przedstawiono instrukcję yield return, która znajduje się wewnątrz pętli for.Każda iteracja treści instrukcji foreach w Process tworzy wywołanie funkcji iteratora Power.Każde wywołanie funkcji iteratora powoduje przejście do następnego wykonania instrukcji yield return, do którego dochodzi podczas następnej iteracji pętli for.
Zwracany typ metody iteratora to IEnumerable, który jest typem interfejsu iteratora.Kiedy metoda iteratora jest wywoływana, zwraca obiekt wyliczeniowy, który zawiera potęgi liczb.
public class PowersOf2
{
static void Main()
{
// Display powers of 2 up to the exponent of 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
// Output: 2 4 8 16 32 64 128 256
}
W poniższym przykładzie pokazano metodę dostępu get, która jest iteratorem.W tym przykładzie każda instrukcja yield return zwraca wystąpienie klasy zdefiniowanej przez użytkownika.
public static class GalaxyClass
{
public static void ShowGalaxies()
{
var theGalaxies = new Galaxies();
foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)
{
Debug.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString());
}
}
public class Galaxies
{
public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy
{
get
{
yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };
yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };
yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };
yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };
}
}
}
public class Galaxy
{
public String Name { get; set; }
public int MegaLightYears { get; set; }
}
}
Specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz Specyfikacja języka C#. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.
Zobacz też
Informacje
Koncepcje
Przewodnik programowania w języku C#