yield (Référence C#)
Lorsque vous utilisez le mot clé yield dans une instruction, vous indiquez que la méthode, l'opérateur, ou l'accesseur get dans lequel elle apparaît est un itérateur. L'utilisation de yield pour définir un itérateur rend une classe explicite supplémentaire inutile (la classe qui contient l'état d'une énumération ; pour obtenir un exemple, consultez IEnumerator) lorsque vous implémentez les modèles IEnumerable et IEnumerator pour un type de collection personnalisé.
L'exemple suivant montre les deux formulaires de l'instruction yield.
yield return <expression>;
yield break;
Notes
Utilisez une instruction yield return pour retourner chaque élément un par un.
Vous consommez une méthode Iterator à l'aide d'une instruction foreach ou d'une requête LINQ. Chaque itération de la boucle foreach appelle la méthode Iterator. Lorsqu'une instruction yield return est atteinte dans la méthode Iterator, expression est retourné, et l'emplacement dans le code est conservé. L'exécution redémarrera à partir de cet emplacement la prochaine fois que la fonction d'itérateur sera appelée.
Utilisez une instruction yield break pour terminer l'itération.
Pour plus d'informations sur les itérateurs, consultez Itérateurs (C# et Visual Basic).
Méthodes Iterator et accesseurs get
La déclaration d'un itérateur doit respecter les spécifications suivantes :
Le type de retour doit être IEnumerable, IEnumerable, IEnumerator, ou IEnumerator.
La déclaration ne peut pas contenir des paramètres ref ou out.
Le type yield d'un itérateur qui retourne IEnumerable ou IEnumerator est object. Si l'itérateur retourne IEnumerable ou IEnumerator, il doit exister une conversion implicite du type de l'expression dans l'instruction yield return au paramètre de type générique.
Vous ne pouvez pas inclure une instruction yield return ou yield break dans les méthodes qui présentent les caractéristiques suivantes :
Méthodes anonymes. Pour plus d'informations, consultez Méthodes anonymes (Guide de programmation C#).
Méthodes qui contiennent des blocs unsafe. Pour plus d'informations, consultez unsafe (référence C#).
Gestion des exceptions
Il ne peut pas y avoir d'instruction yield return dans un bloc try-catch. Une instruction yield return peut se trouver dans le bloc try d'une instruction try-finally.
Une instruction yield break peut se trouver dans un bloc try ou un bloc catch mais pas dans un bloc finally.
Si le corps foreach (en dehors de la méthode Iterator) lève une exception, un bloc finally de la méthode Iterator est exécuté.
Implémentation technique
Le code suivant retourne IEnumerable<string> depuis une méthode Iterator, puis itère au sein de ses éléments.
IEnumerable<string> elements = MyIteratorMethod();
foreach (string element in elements)
{
…
}
L'appel à MyIteratorMethod n'exécute pas le corps de la méthode. À la place, l'appel retourne IEnumerable<string> dans la variable elements.
Dans une itération de la boucle foreach, la méthode MoveNext est appelée pour elements. Cet appel exécute le corps de MyIteratorMethod jusqu'à ce que l'instruction yield return suivante soit atteinte. L'expression retournée par l'instruction yield return détermine non seulement la valeur de la variable element pour la consommation par le corps de boucle mais également la propriété Current des éléments, qui est IEnumerable<string>.
À chaque itération suivante de la boucle foreach, l'exécution du corps de l'itérateur reprend à partir de l'emplacement où elle s'est interrompue, et s'arrête encore lorsqu'elle atteint une instruction yield return. La boucle foreach se termine lorsque à la fin de la méthode Iterator ou lorsqu'une instruction yield break est atteinte.
Exemple
L'exemple suivant comprend une instruction yield return située dans une boucle for. Chaque itération du corps d'instruction foreach dans Process crée un appel à la fonction d'itérateur Power. Chaque appel à la fonction d'itérateur continue vers l'exécution suivante de l'instruction yield return, qui se produit pendant l'itération suivante de la boucle for.
Le type de retour de la méthode Iterator est IEnumerable, qui est un type interface itérateur. Lorsque la méthode Iterator est appelée, elle retourne un objet énumérable contenant les puissances d'un nombre.
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
}
L'exemple suivant illustre un accesseur get qui est un itérateur. Dans cet exemple, chaque instruction yield return retourne une instance d'une classe définie par l'utilisateur.
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; }
}
}
Spécification du langage C#
Pour plus d'informations, voir la Spécification du langage C#. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.