Eu já vi essa sintaxe no MSDN:, yield break
mas não sei o que faz. Alguém sabe?
MyList.Add(...)
apenas fazer yield return ...
. Se você precisa sair do loop prematuramente e retornar a lista de apoio virtual que você usaryield break;
Eu já vi essa sintaxe no MSDN:, yield break
mas não sei o que faz. Alguém sabe?
MyList.Add(...)
apenas fazer yield return ...
. Se você precisa sair do loop prematuramente e retornar a lista de apoio virtual que você usaryield break;
Respostas:
Ele especifica que um iterador chegou ao fim. Você pode pensar yield break
em uma return
declaração que não retorna um valor.
Por exemplo, se você definir uma função como um iterador, o corpo da função poderá ser assim:
for (int i = 0; i < 5; i++)
{
yield return i;
}
Console.Out.WriteLine("You will see me");
Observe que após o loop concluir todos os seus ciclos, a última linha é executada e você verá a mensagem no aplicativo do console.
Ou assim com 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");
Nesse caso, a última instrução nunca é executada porque deixamos a função mais cedo.
break
vez de yield break
no seu exemplo acima? O compilador não se queixa disso.
break
neste caso interromperia o loop, mas não abortaria a execução do método, assim a última linha seria executada e o "Won't see me text" seria realmente visto.
NullReferenceException
obter o enumerador de IEnumerable, enquanto que com a quebra de rendimento, não o fará (há uma instância sem elementos).
yield return x
alertas no compilador, você deseja que esse método seja um açúcar sintático para a criação de um Enumerator
objeto. Este enumerador tem método MoveNext()
e propriedade Current
. MoveNext () executa o método até uma yield return
instrução e transforma esse valor em Current
. Na próxima vez que MoveNext for chamado, a execução continuará a partir daí. yield break
define Current como null, sinalizando o final desse enumerador, para que umforeach (var x in myEnum())
termine.
Termina um bloco iterador (por exemplo, diz que não há mais elementos no IEnumerable).
yield
palavra-chave que você pode iterar coleção em ambas as direções, além disso você pode tomar cada elemento seguinte da coleção não em uma fileira
yield
fazê-lo. não estou dizendo que você está errado, entendo o que você está sugerindo; mas academicamente não há iteradores no .NET, apenas enumeradores (uma direção, encaminhamento) - diferentemente do stdc ++, não há uma "estrutura genérica de iterador" definida no CTS / CLR. O LINQ ajuda a fechar a lacuna com métodos de extensão que utilizam yield return
e também métodos de retorno de chamada , mas são métodos de extensão de primeira classe, não iteradores de primeira classe. o resultado IEnumerable
não pode, por si só, repetir em outra direção que não seja o redirecionamento do chamador.
Diz ao iterador que chegou ao fim.
Como um exemplo:
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
basicamente faz com que um IEnumerable<T>
método se comporte de maneira semelhante a um encadeamento agendado cooperativamente (em oposição a preventivamente).
yield return
é como um thread que chama uma função "agendamento" ou "suspensão" para abrir mão do controle da CPU. Assim como um encadeamento, o IEnumerable<T>
método recupera os controles no ponto imediatamente depois, com todas as variáveis locais tendo os mesmos valores que tinham antes do controle ser liberado.
yield break
é como um thread que chega ao fim de sua função e termina.
As pessoas falam sobre uma "máquina de estado", mas uma máquina de estado é tudo um "fio" realmente é. Um encadeamento possui algum estado (ou seja, valores de variáveis locais) e, toda vez que é agendado, ele executa algumas ações para alcançar um novo estado. O ponto principal yield
é que, diferentemente dos threads do sistema operacional a que estamos acostumados, o código que o utiliza é congelado no tempo até que a iteração seja avançada ou finalizada manualmente.
Todo o assunto dos blocos iteradores é abordado bem neste capítulo de amostra grátis do livro C # in Depth de Jon Skeet .
A yield break
instrução faz com que a enumeração pare. Com efeito, yield break
conclui a enumeração sem retornar nenhum item adicional.
Considere que, na verdade, existem duas maneiras pelas quais um método iterador pode parar de iterar. Em um caso, a lógica do método poderia naturalmente sair do método depois de retornar todos os itens. Aqui está um exemplo:
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.");
}
No exemplo acima, o método do iterador interromperá naturalmente a execução após a localização dos maxCount
primos.
A yield break
declaração é outra maneira de o iterador parar de enumerar. É uma maneira de interromper a enumeração mais cedo. Aqui está o mesmo método acima. Desta vez, o método tem um limite para a quantidade de tempo que o método pode executar.
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.");
}
Observe a chamada para yield break
. Com efeito, está saindo da enumeração mais cedo.
Observe também que o yield break
trabalho funciona de maneira diferente do que apenas uma planície break
. No exemplo acima, yield break
sai do método sem fazer a chamada para Debug.WriteLine(..)
.
Aqui http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/ é um exemplo muito bom:
público estático IEnumerable <int> Range (int min, int max) { enquanto (verdadeiro) { if (min> = max) { quebra de rendimento; } retorno de rendimento min ++; } }
e explicação, que se uma yield break
instrução for atingida em um método, a execução desse método será interrompida sem retorno. Existem algumas situações em que, quando você não deseja dar nenhum resultado, pode usar a quebra de rendimento.
quebra de rendimento é apenas uma maneira de dizer retorno pela última vez e não retornar nenhum valor
por exemplo
// 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 o que você quer dizer com "o que realmente produz quebra", é "como funciona" - consulte o blog de Raymond Chen para obter detalhes https://devblogs.microsoft.com/oldnewthing/20080812-00/?p=21273
Os iteradores C # geram código muito complicado.
A palavra-chave yield é usada junto com a palavra-chave return para fornecer um valor ao objeto enumerador. retorno de rendimento especifica o valor ou valores retornados. Quando a declaração de retorno de rendimento é alcançada, o local atual é armazenado. A execução é reiniciada nesse local na próxima vez que o iterador for chamado.
Para explicar o significado usando um exemplo:
public IEnumerable<int> SampleNumbers() { int counter = 0; yield return counter; counter = counter + 2; yield return counter; counter = counter + 3; yield return counter ; }
Os valores retornados quando iterados são: 0, 2, 5.
É importante observar que a variável de contador neste exemplo é uma variável local. Após a segunda iteração que retorna o valor 2, a terceira iteração começa de onde saiu antes, preservando o valor anterior da variável local denominada counter, que era 2.
yield break
faz
yield return
realmente suporta o retorno de vários valores. Talvez não seja isso que você realmente quis dizer, mas é assim que eu li.
yield break
é que ele não contém um enumerador no nível do idioma como a foreach
- ao usar um enumerador, o yield break
valor real é fornecido. este exemplo parece um loop desenrolado. você quase nunca verá esse código no mundo real (todos nós podemos pensar em alguns casos extremos, com certeza) também, não há "iterador" aqui. o "bloco iterador" não pode se estender além do método como uma questão de especificação de linguagem. o que realmente está sendo retornado é um "enumerável", consulte também: stackoverflow.com/questions/742497/…