Que fait "yield break" Dans C#?
j'ai vu cette syntaxe dans MSDN: yield break
, mais je ne sais pas ce que ça fait. Personne ne sait?
10 réponses
il spécifie qu'un itérateur est arrivé à sa fin. Vous pouvez penser à yield break
comme une déclaration return
qui ne renvoie pas de valeur.
Par exemple, si vous définissez une fonction comme un itérateur, le corps de la fonction peut ressembler à ceci:
for (int i = 0; i < 5; i++)
{
yield return i;
}
Console.Out.WriteLine("You will see me");
notez qu'après que la boucle a terminé tous ses cycles, la dernière ligne est exécutée et vous verrez le message dans votre application de console.
ou comme ceci avec yield break
:
int i = 0;
while (true)
{
if (i < 5)
{
yield return i;
}
else
{
// note that i++ will not be executed after this
yield break;
}
i++;
}
Console.Out.WriteLine("Won't see me");
Dans ce cas, la dernière instruction n'est jamais exécutée parce que nous avons quitté la fonction tôt.
termine un bloc itérateur (par exemple, il dit qu'il n'y a plus d'éléments dans le IEnumerable).
indique à l'itérateur qu'il a atteint la fin.
comme exemple:
public interface INode
{
IEnumerable<Node> GetChildren();
}
public class NodeWithTenChildren : INode
{
private Node[] m_children = new Node[10];
public IEnumerable<Node> GetChildren()
{
for( int n = 0; n < 10; ++n )
{
yield return m_children[ n ];
}
}
}
public class NodeWithNoChildren : INode
{
public IEnumerable<Node> GetChildren()
{
yield break;
}
}
yield
rend fondamentalement une méthode IEnumerable<T>
se comporte de la même manière qu'un filetage programmé coopératif (par opposition à un filetage préemptif).
yield return
est comme un fil appelant une fonction "schedule" ou "sleep" pour abandonner le contrôle du CPU. Tout comme un thread, la méthode IEnumerable<T>
récupère les contrôles au point immédiatement après, toutes les variables locales ayant les mêmes valeurs qu'avant l'abandon du contrôle.
yield break
est comme un fil qui atteint la fin de sa fonction et se termine.
les gens parlent d'une "machine d'état", mais une machine d'état est tout un" fil " est vraiment. Un fil a un certain état (c'est-à-dire. valeurs des variables locales), et chaque fois qu'elle est programmée, elle prend des mesures pour atteindre un nouvel état. Le point clé à propos de yield
est que, contrairement aux threads du système d'exploitation auxquels nous sommes habitués, le code qui l'utilise est figé dans le temps jusqu'à ce que l'itération soit avancé manuellement ou terminé.
tout le sujet des blocs itérateurs est bien traité dans ce chapitre échantillon gratuit du livre de Jon Skeet C# en profondeur .
ici http://www.alteridem.net/2007/08/22/the-yield-statement-in-c / est un très bon exemple:
public static IEnumerable<int> Range( int min, int max ) { while ( true ) { if ( min >= max ) { yield break; } yield return min++; } }
et explication, que si une instruction yield break
est frappée dans une méthode, l'exécution de cette méthode s'arrête sans retour. Il y a des situations de temps, quand vous ne voulez pas donner de résultat, alors vous pouvez utiliser la limite de rendement.
l'énoncé yield break
fait cesser l'énumération. En fait, yield break
complète le recensement sans retourner d'éléments supplémentaires.
considérer qu'il y a en fait deux façons dont une méthode itératrice pourrait arrêter itérating. Dans un cas, la logique de la méthode pourrait naturellement sortir de la méthode après avoir retourné tous les éléments. Voici un exemple:
IEnumerable<uint> FindPrimes(uint startAt, uint maxCount)
{
for (var i = 0UL; i < maxCount; i++)
{
startAt = NextPrime(startAt);
yield return startAt;
}
Debug.WriteLine("All the primes were found.");
}
Dans l'exemple ci-dessus, la méthode iterator naturellement arrêter l'exécution une fois que les amorces maxCount
ont été trouvées.
l'énoncé yield break
est une autre façon pour l'itérateur de cesser d'énumérer. C'est un moyen de sortir de l'énumération tôt. Ici c'est la même méthode que ci-dessus. Cette fois, la méthode a une limite sur la quantité de temps que la méthode peut s'exécuter.
IEnumerable<uint> FindPrimes(uint startAt, uint maxCount, int maxMinutes)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
for (var i = 0UL; i < maxCount; i++)
{
startAt = NextPrime(startAt);
yield return startAt;
if (sw.Elapsed.TotalMinutes > maxMinutes)
yield break;
}
Debug.WriteLine("All the primes were found.");
}
notez l'appel à yield break
. En fait, il sort de l'énumération plus tôt.
remarquez aussi que le yield break
fonctionne différemment d'un simple break
. Dans l'exemple ci-dessus, yield break
sort de la méthode sans faire l'appel à Debug.WriteLine(..)
.
si ce que vous voulez dire par "qu'est-ce que la rupture de rendement fait vraiment", c'est "comment ça marche" - voir le blog de Raymond Chen pour plus de détails http://blogs.msdn.com/oldnewthing/archive/2008/08/12/8849519.aspx
C# itérateurs peu de code compliqué.
yield break est juste une façon de dire retour pour la dernière fois et ne pas renvoyer une valeur
E. g
// returns 1,2,3,4,5
IEnumerable<int> CountToFive()
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
yield return 5;
yield break;
yield return 6;
yield return 7;
yield return 8;
yield return 9;
}
le mot-clé yield est utilisé avec le mot-clé return pour fournir une valeur à l'objet enumerator. taux de retour spécifie la valeur ou les valeurs retournées. Lorsque la déclaration de rendement est atteinte, l'emplacement courant est stocké. L'exécution est redémarrée à partir de cet emplacement la prochaine fois que l'itérateur est appelé.
pour expliquer le sens à l'aide d'un exemple:
public IEnumerable<int> SampleNumbers() { int counter = 0; yield return counter; counter = counter + 2; yield return counter; counter = counter + 3; yield return counter ; }
Les valeurs retournées lors de cette itération sont: 0, 2, 5.
il est important de noter que la variable counter dans cet exemple est une variable locale. après la deuxième itération qui renvoie la valeur de 2, la troisième itération commence là où elle est partie avant, tout en conservant la valeur précédente de la variable locale appelée counter qui était 2.