Mes deux cents sur le mot-clé yield en C #

Le mot clé yield, introduit pour la première fois en C # 2.0, T renvoie un objet qui implémente l'interface IEnumerable. L'interface IEnumerable expose un IEnumerator qui peut être utilisé pour itérer une collection non générique à l'aide d'une boucle foreach en C #. Vous pouvez utiliser le mot clé yield pour indiquer que la méthode ou un accesseur get dans lequel il a été utilisé est un itérateur.

Il existe deux manières d'utiliser le mot clé yield: En utilisant les instructions "yield return" et "yield break". La syntaxe des deux est indiquée ci-dessous.

yield return ;

yield break;

Pourquoi utiliser le mot clé yield?

Le mot-clé yield peut effectuer une itération complète sans avoir besoin de créer une collection temporaire. En d'autres termes, lorsque vous utilisez l'instruction «yield return» dans un itérateur, vous n'avez pas besoin de créer une collection temporaire pour stocker les données avant leur retour. Vous pouvez profiter de l'instruction yield return pour renvoyer chaque élément de la collection un par un, et vous pouvez utiliser l'instruction "yield return" avec des itérateurs dans une méthode ou un accesseur get.

Notez que le contrôle est renvoyé à l'appelant chaque fois que l'instruction "yield return" est rencontrée et exécutée. Plus important encore, à chaque appel de ce type, les informations d'état de l'appelé sont conservées afin que l'exécution puisse se poursuivre immédiatement après l'instruction yield lorsque le contrôle est renvoyé.

Regardons un exemple. L'extrait de code suivant illustre comment le mot clé yield peut être utilisé pour renvoyer un numéro de Fibonacci. La méthode accepte un entier comme argument qui représente le décompte des nombres de Fibonacci à générer.

static IEnumerable GenerateFibonacciNumbers(int n)

       {

           for (int i = 0, j = 0, k = 1; i < n; i++)

          {

               yield return j;

               int temp = j + k;

               j = k;

               k = temp;

           }

       }

Comme indiqué dans l'extrait de code ci-dessus, l'instruction "yield return j;" renvoie les nombres de Fibonacci un par un sans sortir de la boucle «for». En d'autres termes, les informations d'état sont conservées. Voici comment la méthode GenerateFibonacciNumbers peut être appelée.

foreach (int x in GenerateFibonacciNumbers(10))

   {

       Console.WriteLine(x);

   }

Comme vous pouvez le constater, il n'est pas nécessaire de créer une liste ou un tableau intermédiaire pour contenir les numéros de fibonacci qui doivent être générés et renvoyés à l'appelant.

Notez que sous les couvertures, le mot-clé yield crée une machine à états pour conserver les informations d'état. Le MSDN indique: «Lorsqu'une instruction yield return est atteinte dans la méthode iterator, l'expression est renvoyée et l'emplacement actuel dans le code est conservé. L'exécution est redémarrée à partir de cet emplacement la prochaine fois que la fonction d'itérateur est appelée.

Un autre avantage de l'utilisation du mot-clé yield est que les éléments renvoyés sont créés uniquement à la demande. À titre d'exemple, l'accesseur get suivant renvoie les nombres pairs entre 1 et 10.

public static IEnumerable EvenNumbers

       {

           avoir

           {

               pour (int i = 1; i <= 10; i ++)

               {

                   si ((i% 2) == 0)

                   rendement retour i;

               }

           }

       }

Vous pouvez accéder à la propriété statique EvenNumbers pour afficher les nombres pairs entre 1 et 10 dans la fenêtre de la console à l'aide de l'extrait de code ci-dessous.

foreach (int i in EvenNumbers)

     {

         Console.WriteLine(i);

     }

Vous pouvez utiliser l'instruction "yield break" dans un itérateur lorsqu'il n'y a plus de valeurs à renvoyer. L'instruction "yield break" est utilisée pour terminer l'énumération.

public IEnumerable GetData(IEnumerable items)

{

   if (null == items)

       yield break;

   foreach (T item in items)

       yield return item;

}

Reportez-vous à la liste des codes ci-dessus. Notez comment une vérification est effectuée pour voir si le paramètre "items" est nul. Lorsque vous appelez la méthode GetData () dans un itérateur et avec null comme paramètre, le contrôle revient simplement à l'appelant sans qu'aucune valeur ne soit renvoyée.

Points à retenir

Lorsque vous utilisez le mot-clé yield, gardez ces points à l'esprit:

  • Vous ne pouvez pas avoir l'instruction yield return dans un bloc try-catch bien que vous puissiez l'avoir dans un bloc try-finally
  • Vous ne pouvez pas avoir l'instruction yield break dans un bloc finally
  • Le type de retour de la méthode où le rendement a été utilisé doit être IEnumerable, IEnumerable, IEnumerator ou IEnumerator
  • Vous ne pouvez pas avoir de paramètre ref ou out dans votre méthode dans lequel le rendement a été utilisé
  • Vous ne pouvez pas utiliser les instructions "yield return" ou "yield break" dans des méthodes anonymes
  • Vous ne pouvez pas utiliser les instructions "yield return" ou "yield break" dans des méthodes "unsafe", c'est-à-dire des méthodes marquées avec le mot clé "unsafe" pour désigner un contexte non sécurisé