Ho visto questa sintassi in MSDN:, yield break
ma non so cosa faccia. Qualcuno sa?
MyList.Add(...)
fare yield return ...
. Se hai bisogno di uscire prematuramente dal loop e restituire la backing list virtuale che usiyield break;
Ho visto questa sintassi in MSDN:, yield break
ma non so cosa faccia. Qualcuno sa?
MyList.Add(...)
fare yield return ...
. Se hai bisogno di uscire prematuramente dal loop e restituire la backing list virtuale che usiyield break;
Risposte:
Specifica che un iteratore è giunto al termine. Puoi pensare yield break
a return
un'istruzione che non restituisce un valore.
Ad esempio, se si definisce una funzione come iteratore, il corpo della funzione potrebbe apparire così:
for (int i = 0; i < 5; i++)
{
yield return i;
}
Console.Out.WriteLine("You will see me");
Nota che dopo che il ciclo ha completato tutti i suoi cicli, l'ultima riga viene eseguita e vedrai il messaggio nell'app della console.
O così con 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");
In questo caso l'ultima istruzione non viene mai eseguita perché abbiamo lasciato la funzione in anticipo.
break
invece che yield break
nel tuo esempio sopra? Il compilatore non si lamenta di questo.
break
in questo caso fermerebbe il ciclo, ma non interromperebbe l'esecuzione del metodo, quindi l'ultima riga verrebbe eseguita e il "Won't see me text" verrebbe effettivamente visto.
NullReferenceException
ottenere l'enumeratore di IEnumerable, mentre con l'interruzione del rendimento non si ottiene (esiste un'istanza senza elementi).
yield return x
avvisi del compilatore, si desidera che questo metodo sia uno zucchero sintattico per la creazione di un Enumerator
oggetto. Questo enumeratore ha metodo MoveNext()
e proprietà Current
. MoveNext () esegue il metodo fino a yield return
un'istruzione e trasforma quel valore in Current
. Al successivo richiamo di MoveNext, l'esecuzione continua da lì. yield break
imposta Current su null, segnalando la fine di questo enumeratore, in modo che un foreach (var x in myEnum())
end finisca.
Termina un blocco iteratore (ad esempio dice che non ci sono più elementi in IEnumerable).
yield
parola chiave puoi iterare la raccolta in entrambe le direzioni, inoltre puoi prendere ogni elemento successivo della raccolta non in fila
yield
devi farlo. non sto dicendo che ti sbagli, capisco cosa stai suggerendo; ma accademicamente non ci sono iteratori in .NET, solo enumeratori (una direzione, avanti) - a differenza di stdc ++ non esiste un "framework iteratore generico" definito nel CTS / CLR. LINQ aiuta a colmare il divario con i metodi di estensione che utilizzano yield return
e anche i metodi di callback , ma sono metodi di estensione di prima classe, non iteratori di prima classe. il risultante IEnumerable
non può di per sé iterare in alcuna direzione diversa dall'inoltro del chiamante.
Indica all'iteratore che ha raggiunto la fine.
Come esempio:
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
fondamentalmente fa in modo che un IEnumerable<T>
metodo si comporti in modo simile a un thread pianificato in modo cooperativo (anziché preventivamente).
yield return
è come un thread che chiama una funzione "programma" o "sospensione" per rinunciare al controllo della CPU. Proprio come un thread, il IEnumerable<T>
metodo recupera i controlli nel punto immediatamente successivo, con tutte le variabili locali che hanno gli stessi valori che avevano prima che il controllo venisse abbandonato.
yield break
è come un thread che raggiunge la fine della sua funzione e termina.
Le persone parlano di una "macchina a stati", ma una macchina a stati è tutto un "thread". Un thread ha un certo stato (vale a dire valori di variabili locali) e ogni volta che è pianificato prende alcune azioni per raggiungere un nuovo stato. Il punto chiave yield
è che, a differenza dei thread del sistema operativo a cui siamo abituati, il codice che lo utilizza viene congelato nel tempo fino a quando l'iterazione non viene avanzata o terminata manualmente.
L'intero argomento dei blocchi di iteratori è trattato bene in questo capitolo di esempio gratuito del libro C # di Depth di Jon Skeet .
L' yield break
istruzione provoca l'arresto dell'enumerazione. In effetti, yield break
completa l'enumerazione senza restituire altri elementi.
Considera che in realtà ci sono due modi in cui un metodo iteratore potrebbe smettere di iterare. In un caso, la logica del metodo potrebbe naturalmente uscire dal metodo dopo aver restituito tutti gli elementi. Ecco un esempio:
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.");
}
Nell'esempio sopra, il metodo iteratore interromperà naturalmente l'esecuzione una volta maxCount
trovati i numeri primi.
La yield break
dichiarazione è un altro modo per l'iteratore di smettere di enumerare. È un modo per uscire presto dall'enumerazione. Ecco lo stesso metodo di cui sopra. Questa volta, il metodo ha un limite alla quantità di tempo che il metodo può eseguire.
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.");
}
Si noti la chiamata a yield break
. In effetti, sta uscendo presto dall'enumerazione.
Notare anche che yield break
funziona diversamente da una semplice pianura break
. Nell'esempio sopra, yield break
esce dal metodo senza effettuare la chiamata a Debug.WriteLine(..)
.
Qui http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/ è un ottimo esempio:
pubblico IEnumerable <int> Range (int min, int max) { while (true) { if (min> = max) { pausa di rendimento; } rendimento minimo min ++; } }
e spiegazione, che se yield break
un'istruzione viene colpita all'interno di un metodo, l'esecuzione di quel metodo si interrompe senza ritorno. Ci sono alcune situazioni temporali, in cui non si desidera dare alcun risultato, quindi è possibile utilizzare l'intervallo di rendimento.
la rottura del rendimento è solo un modo per dire ritorno per l'ultima volta e non restituire alcun valore
per esempio
// 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;
}
Se ciò che intendi con "cosa fa realmente la rottura del rendimento", è "come funziona" - Vedi il blog di Raymond Chen per i dettagli https://devblogs.microsoft.com/oldnewthing/20080812-00/?p=21273
Gli iteratori C # generano un codice molto complicato.
La parola chiave yield viene utilizzata insieme alla parola chiave return per fornire un valore all'oggetto enumeratore. il rendimento restituisce il valore oi valori restituiti. Quando viene raggiunta l'istruzione return return, viene memorizzata la posizione corrente. L'esecuzione viene riavviata da questa posizione al successivo richiamo dell'iteratore.
Per spiegare il significato usando un esempio:
public IEnumerable<int> SampleNumbers() { int counter = 0; yield return counter; counter = counter + 2; yield return counter; counter = counter + 3; yield return counter ; }
I valori restituiti quando viene ripetuto sono: 0, 2, 5.
È importante notare che la variabile contatore in questo esempio è una variabile locale. Dopo la seconda iterazione che restituisce il valore di 2, la terza iterazione inizia da dove era stata lasciata prima, preservando il valore precedente della variabile locale denominata counter che era 2.
yield break
fa
yield return
realtà supporti la restituzione di più valori. Forse non è quello che volevi dire, ma è così che l'ho letto.
yield break
è che non contiene un enumeratore a livello di lingua come un foreach
- quando si utilizza un enumeratore yield break
fornisce un valore reale. questo esempio sembra un ciclo non srotolato. non vedrai quasi mai questo codice nel mondo reale (possiamo tutti pensare ad alcuni casi limite, certo), anche qui non c'è un "iteratore". il "blocco iteratore" non può estendersi oltre il metodo come una questione di specifica del linguaggio. ciò che viene effettivamente restituito è un "enumerabile", vedi anche: stackoverflow.com/questions/742497/…