12
votes

Modèle de travail du rendement de rendement

Lorsque j'ai un bloc de code

static void Main()
{

  foreach (int i in YieldDemo.SupplyIntegers())
  {
    Console.WriteLine("{0} is consumed by foreach iteration", i);
  }
}


 class YieldDemo
  {
    public static IEnumerable<int> SupplyIntegers()
     {
         yield return 1;
         yield return 2;
          yield return 3;
       }
   }


4 commentaires

Remandez à propos d'un livre: C # En profondeur (Manning, Skeet), Chapitre 6. C'est le chapitre d'échantillon gratuit et couvre les blocs d'itérateurs. Ce n'est pas vraiment un livre C # débutant (loin de celui-ci), mais vous aurez du mal à trouver une meilleure référence sur ce sujet.


Si les privilèges ont permis de demander "n'ont pas écrit de livres?"


Non, je n'ai pas. Je fais une certaine lecture pour un éditeur et j'écris parfois l'article étrange, etc. mais pas de livres de moi.


Je serai heureux si vous faites celui-ci, car j'ai vu votre explication à quelques questions.Il correspond du programmateur de niveau de débutant au vétéran


4 Réponses :


34
votes

Nope - loin de là; Je vais écrire une version à long terme pour vous ... il est trop grungy!


Notez qu'il vous aide également si vous comprenez que le foreach code> est réellement: p> XXX PRE>


using System;
using System.Collections;
using System.Collections.Generic;
static class Program
{
    static void Main()
    {

        foreach (int i in YieldDemo.SupplyIntegers())
        {
            Console.WriteLine("{0} is consumed by foreach iteration", i);
        }
    }
}

 class YieldDemo
  {

    public static IEnumerable<int> SupplyIntegers()
     {
         return new YieldEnumerable();
       }
    class YieldEnumerable : IEnumerable<int>
    {
        public IEnumerator<int> GetEnumerator()
        {
            return new YieldIterator();
        }
        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
    }
    class YieldIterator : IEnumerator<int>
    {
        private int state = 0;
        private int value;
        public int Current { get { return value; } }
        object IEnumerator.Current { get { return Current; } }
        void IEnumerator.Reset() { throw new NotSupportedException(); }
        void IDisposable.Dispose() { }
        public bool MoveNext()
        {
            switch (state)
            {
                case 0: value = 1; state = 1;  return true;
                case 1: value = 2; state = 2;  return true;
                case 2: value = 3; state = 3; return true;
                default: return false;
            }
        }
    }
}


9 commentaires

Incroyable que les gens évoquent cela avant que cela soit une réponse utile.


@Joren: C'est à quel point le Marc est bon. ;) Excellente réponse Marc!


C'est vraiment simple, quand Marc dit qu'il va poster quelque chose, vous pouvez parier à peu près que ça va être juste.


Explication irrésistible et notes impeccables.Les débutants que j'ai imbibé suffisamment de choses de vous tous. Merci tout le monde fro soin. :)


@Joren: C'est un exemple du système de réputation fonctionnant bien. Les gens connaissent @Marc Gravell de ses précédents postes, il dit qu'il l'écrira Longhand, c'est-à-dire un bon moyen de l'expliquer et de le faire, et il le fait, cela signifie que nous n'avons pas à le faire.


Bonjour à tous, veuillez me suggérer un livre de niveau débutant pour enrichir mes connaissances en C #.


@Hamish - J'ai une grande confiance de la confiance dans les personnes comme Marc Qui j'ai vu régulièrement donner de très bonnes réponses, mais je ne voterais toujours jamais sur une réponse basée sur autre chose que le mérite spécifique de cette réponse. Mais je suppose que je ne devrais pas parler trop méta ici. :)


@ Generix: C # En profondeur (Manning, Skeet), Chapitre 6. C'est le chapitre d'échantillon gratuit et couvre les blocs d'itérateurs. Ce n'est pas vraiment un livre C # débutant (loin de celui-ci), mais vous aurez du mal à trouver une meilleure référence sur ce sujet.


@Joren a raison. Je n'aurais pas voté pour cela non plus. Mais si j'ai vu (par exemple) que Jon avait un marqueur "en cours" similaire, je n'aurais pas dépensé beaucoup d'efforts en le despliquant; que était mon intention.



3
votes

C'est juste un sucre de syntaxe, .NET génère une classe d'ienumerator pour vous et implémente les méthodes MOVENMENTEXT, COURANT ET RESET, que génère une classe IEnumarable Getenumerator de laquelle Inumerator, vous pouvez voir que les classes magiques par .NET réflecteur ou illaste. < / p>

Voir aussi ici


0 commentaires

1
votes

En bref, (tandis que vous attendez la version à long terme de Marc) lorsque le compilateur voit des déclarations de rendement, il crée une nouvelle instance d'une classe personnalisée pour vous qui implémente une interface appelée ienumerator , qui a des méthodes actuelles () et movenext () et garde la trace de l'endroit où vous êtes actuellement dans le processus d'itération ... Dans l'affaire ci-dessus comme exemple de votre exemple Cela garderait également une trace des valeurs de la liste à être énumérées.


0 commentaires

2
votes

Il suffit de mettre, des blocs d'itérateur (ou des méthodes avec des instructions code> de rendement code>, si vous le pouvez) sont transformés par le compilateur en une classe générée par le compilateur. Cette classe implémente ienumerator code> et l'instruction code> code> est transformée en un "état" pour cette classe.

Par exemple, ceci: p> xxx

peut être transformé en quelque chose de similaire à: p>

switch (state)
{
    case 0: goto LABEL_A;
    case 1: goto LABEL_B;
    case 2: goto LABEL_C;
}
LABEL_A:
    return 1;
LABEL_B:
    return 2;
LABEL_C:
    return 3;


0 commentaires