Тем не менее, документация MSDN упоминает об этом, но не объясняет это. Это плохой способ дразнить голодных до знаний разработчиков.
Фил
3
Возврат доходности устраняет необходимость в вспомогательном списке, то есть вам не нужно кодировать что-то вроде MyList.Add(...)просто делайте yield return .... Если вам нужно преждевременно выйти из цикла и вернуть используемый вами виртуальный резервный списокyield break;
The Muffin Man
Ответы:
529
Это указывает, что итератор подошел к концу. Вы можете думать yield breakкак о returnзаявлении, которое не возвращает значение.
Например, если вы определяете функцию как итератор, тело функции может выглядеть так:
for(int i =0; i <5; i++){yieldreturn i;}Console.Out.WriteLine("You will see me");
Обратите внимание, что после того, как цикл завершил все свои циклы, выполняется последняя строка, и вы увидите сообщение в своем консольном приложении.
Или как это с yield break:
int i =0;while(true){if(i <5){yieldreturn i;}else{// note that i++ will not be executed after thisyieldbreak;}
i++;}Console.Out.WriteLine("Won't see me");
В этом случае последний оператор никогда не выполняется, потому что мы рано вышли из функции.
Может быть, это просто, breakа не yield breakв вашем примере выше? Компилятор не жалуется на это.
Орад
85
В breakэтом случае простой @orad остановит цикл, но не прервет выполнение метода, поэтому будет выполнена последняя строка и на самом деле будет виден текст «Не вижу меня».
Дамир Зекич
5
@Damir Zekić Не могли бы вы также добавить к своему ответу, почему вы предпочитаете разрыв доходности, а не разницу между ними?
Бруно Коста
11
@ DamirZekić, возвращающий ноль и разрыв доходности, не то же самое. Если вы вернете ноль, то вы можете иметьNullReferenceException получить перечислитель IEnumerable, тогда как с yield break вы этого не сделаете (есть экземпляр без элементов).
Бруно Коста
6
@BrunoCosta Попытка регулярного возврата в одном и том же методе приводит к ошибке компилятора. Используя yield return xоповещения компилятора, вы хотите, чтобы этот метод был синтаксическим сахаром для создания Enumeratorобъекта. Этот перечислитель имеет метод MoveNext()и свойство Current. MoveNext () выполняет метод до yield returnоператора и преобразует это значение в Current. При следующем вызове MoveNext выполнение будет продолжено. yield breakустанавливает Current в null, сигнализируя об окончании этого перечислителя, так что a foreach (var x in myEnum())будет заканчиваться.
Wolfzoon
57
Завершает блок итератора (например, говорит, что в IEnumerable больше нет элементов).
с [+1] - хотя академически в .NET нет итераторов. только счетчики (в одном направлении, вперед.)
Шон Уилсон
@Shaun Wilson, но с помощью yieldключевого слова вы можете выполнять итерацию коллекции в обоих направлениях, более того, вы можете брать каждый следующий элемент коллекции не подряд
monstr
@monstr вы можете перебирать коллекцию любым способом, и вам не нужно yieldэто делать. я не говорю, что вы не правы, я понимаю, что вы предлагаете; но академически в .NET нет итераторов, только перечислители (в одном направлении, вперед) - в отличие от stdc ++, в CTS / CLR не определена «универсальная структура итераторов». LINQ помогает сократить разрыв с помощью методов расширения, которые используют, yield returnа также методы обратного вызова , но они являются методами расширения первого класса, а не итераторами первого класса. результирующее IEnumerableсамо по себе не может повторяться в любом направлении, кроме пересылки по отношению к вызывающему.
Шон Уилсон,
29
Сообщает итератору, что он достиг конца.
Например:
publicinterfaceINode{IEnumerable<Node>GetChildren();}publicclassNodeWithTenChildren:INode{privateNode[] m_children =newNode[10];publicIEnumerable<Node>GetChildren(){for(int n =0; n <10;++n ){yieldreturn m_children[ n ];}}}publicclassNodeWithNoChildren:INode{publicIEnumerable<Node>GetChildren(){yieldbreak;}}
yieldв основном заставляет IEnumerable<T>метод вести себя подобно кооперативному (в отличие от упреждающего) запланированному потоку.
yield returnэто как поток, вызывающий функцию «schedule» или «sleep» для отказа от управления процессором. Точно так же, как поток, IEnumerable<T>метод восстанавливает элементы управления в точке сразу же после того, как все локальные переменные имеют те же значения, что и до того, как управление было прекращено.
yield break это как поток, достигающий конца своей функции и заканчивающийся.
Люди говорят о «государственном автомате», но конечный автомат - это действительно «нить». Поток имеет некоторое состояние (т. Е. Значения локальных переменных), и каждый раз, когда он запланирован, он предпринимает некоторые действия для достижения нового состояния. Ключевым моментом здесь yieldявляется то, что, в отличие от потоков операционной системы, к которым мы привыкли, код, который его использует, заморожен во времени, пока итерация не будет расширена или завершена вручную.
yield breakУтверждение вызывает перечисление для остановки. По сути, yield breakзавершает перечисление без возврата каких-либо дополнительных элементов.
Учтите, что на самом деле метод итератора может прекратить итерации двумя способами. В одном случае логика метода могла естественным образом выйти из метода после возврата всех элементов. Вот пример:
IEnumerable<uint>FindPrimes(uint startAt,uint maxCount){for(var i =0UL; i < maxCount; i++){
startAt =NextPrime(startAt);yieldreturn startAt;}Debug.WriteLine("All the primes were found.");}
В приведенном выше примере метод итератора естественным образом прекратит выполнение, как maxCountтолько будут найдены простые числа.
Это yield breakутверждение - еще один способ для итератора прекратить перечисление. Это способ вырваться из списка рано. Здесь тот же метод, что и выше. На этот раз метод имеет ограничение на количество времени, которое метод может выполнить.
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);yieldreturn startAt;if(sw.Elapsed.TotalMinutes> maxMinutes)yieldbreak;}Debug.WriteLine("All the primes were found.");}
Обратите внимание на звонок yield break. По сути, он рано выходит из списка.
Также обратите внимание, что все yield breakработает иначе, чем просто break. В приведенном выше примере, yield breakвыход из метода без вызова Debug.WriteLine(..).
public static IEnumerable <int> Range (int min, int max)
{
пока (правда)
{
если (мин> = макс)
{
разрыв доходности;
}
доходность возврата мин ++;
}
}
и объяснение, что если yield breakв метод попадает оператор, выполнение этого метода прекращается без возврата. Существуют временные ситуации, когда вы не хотите давать какой-либо результат, тогда вы можете использовать предел доходности.
Ну, они сложны, только если вы заботитесь о коде, в который они компилируются. Код, который их использует, довольно прост.
Роберт Росни
@ Роберт, вот что я имел в виду, поэтому я обновил ответ, включив твой комментарий
Тони Ли
-2
Ключевое слово yield используется вместе с ключевым словом return для предоставления значения объекту перечислителя. yield return указывает возвращаемое значение или значения. Когда достигается отчет о доходности, текущее местоположение сохраняется. Выполнение возобновляется с этого места при следующем вызове итератора.
Важно отметить, что переменная counter в этом примере является локальной переменной. После второй итерации, которая возвращает значение 2, третья итерация начинается с того места, где она была ранее, сохраняя предыдущее значение локальной переменной с именем counter, равное 2.
Я не думаю, что на yield returnсамом деле поддерживает возвращение нескольких значений. Может быть, это не то, что вы на самом деле имели в виду, но так я это прочитал.
Сэм
Sam - метод SampleNumbers с несколькими операторами yield return на самом деле работает, значение итератора возвращается немедленно и выполнение возобновляется при запросе следующего значения. Я видел, как люди заканчивают такой метод "разрывом доходности", но это не нужно. Попадание в конец метода также завершает итератор
Лорен Полсен
причина того, что это плохой пример, yield breakзаключается в том, что он не содержит перечислителя уровня языка, такого как foreach- при использовании перечислителя yield breakобеспечивает реальное значение. этот пример выглядит как развернутый цикл. вы почти никогда не увидите этот код в реальном мире (мы все можем подумать о некоторых крайних случаях, конечно же), здесь нет итератора. «блок итератора» не может выходить за пределы метода в зависимости от спецификации языка. то, что фактически возвращается, является «перечислимым», см. также: stackoverflow.com/questions/742497/…
MyList.Add(...)
просто делайтеyield return ...
. Если вам нужно преждевременно выйти из цикла и вернуть используемый вами виртуальный резервный списокyield break;
Ответы:
Это указывает, что итератор подошел к концу. Вы можете думать
yield break
как оreturn
заявлении, которое не возвращает значение.Например, если вы определяете функцию как итератор, тело функции может выглядеть так:
Обратите внимание, что после того, как цикл завершил все свои циклы, выполняется последняя строка, и вы увидите сообщение в своем консольном приложении.
Или как это с
yield break
:В этом случае последний оператор никогда не выполняется, потому что мы рано вышли из функции.
источник
break
а неyield break
в вашем примере выше? Компилятор не жалуется на это.break
этом случае простой @orad остановит цикл, но не прервет выполнение метода, поэтому будет выполнена последняя строка и на самом деле будет виден текст «Не вижу меня».NullReferenceException
получить перечислитель IEnumerable, тогда как с yield break вы этого не сделаете (есть экземпляр без элементов).yield return x
оповещения компилятора, вы хотите, чтобы этот метод был синтаксическим сахаром для созданияEnumerator
объекта. Этот перечислитель имеет методMoveNext()
и свойствоCurrent
. MoveNext () выполняет метод доyield return
оператора и преобразует это значение вCurrent
. При следующем вызове MoveNext выполнение будет продолжено.yield break
устанавливает Current в null, сигнализируя об окончании этого перечислителя, так что aforeach (var x in myEnum())
будет заканчиваться.Завершает блок итератора (например, говорит, что в IEnumerable больше нет элементов).
источник
yield
ключевого слова вы можете выполнять итерацию коллекции в обоих направлениях, более того, вы можете брать каждый следующий элемент коллекции не подрядyield
это делать. я не говорю, что вы не правы, я понимаю, что вы предлагаете; но академически в .NET нет итераторов, только перечислители (в одном направлении, вперед) - в отличие от stdc ++, в CTS / CLR не определена «универсальная структура итераторов». LINQ помогает сократить разрыв с помощью методов расширения, которые используют,yield return
а также методы обратного вызова , но они являются методами расширения первого класса, а не итераторами первого класса. результирующееIEnumerable
само по себе не может повторяться в любом направлении, кроме пересылки по отношению к вызывающему.Сообщает итератору, что он достиг конца.
Например:
источник
yield
в основном заставляетIEnumerable<T>
метод вести себя подобно кооперативному (в отличие от упреждающего) запланированному потоку.yield return
это как поток, вызывающий функцию «schedule» или «sleep» для отказа от управления процессором. Точно так же, как поток,IEnumerable<T>
метод восстанавливает элементы управления в точке сразу же после того, как все локальные переменные имеют те же значения, что и до того, как управление было прекращено.yield break
это как поток, достигающий конца своей функции и заканчивающийся.Люди говорят о «государственном автомате», но конечный автомат - это действительно «нить». Поток имеет некоторое состояние (т. Е. Значения локальных переменных), и каждый раз, когда он запланирован, он предпринимает некоторые действия для достижения нового состояния. Ключевым моментом здесь
yield
является то, что, в отличие от потоков операционной системы, к которым мы привыкли, код, который его использует, заморожен во времени, пока итерация не будет расширена или завершена вручную.источник
Вся тема блоков итераторов хорошо освещена в этой бесплатной главе из книги Джона Скита C # in Depth .
источник
yield break
Утверждение вызывает перечисление для остановки. По сути,yield break
завершает перечисление без возврата каких-либо дополнительных элементов.Учтите, что на самом деле метод итератора может прекратить итерации двумя способами. В одном случае логика метода могла естественным образом выйти из метода после возврата всех элементов. Вот пример:
В приведенном выше примере метод итератора естественным образом прекратит выполнение, как
maxCount
только будут найдены простые числа.Это
yield break
утверждение - еще один способ для итератора прекратить перечисление. Это способ вырваться из списка рано. Здесь тот же метод, что и выше. На этот раз метод имеет ограничение на количество времени, которое метод может выполнить.Обратите внимание на звонок
yield break
. По сути, он рано выходит из списка.Также обратите внимание, что все
yield break
работает иначе, чем простоbreak
. В приведенном выше примере,yield break
выход из метода без вызоваDebug.WriteLine(..)
.источник
Вот http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/ это очень хороший пример:
и объяснение, что если
yield break
в метод попадает оператор, выполнение этого метода прекращается без возврата. Существуют временные ситуации, когда вы не хотите давать какой-либо результат, тогда вы можете использовать предел доходности.источник
yield break - это просто способ сказать return в последний раз и не возвращать никакого значения
например
источник
Если то, что вы подразумеваете под «что действительно дает доходность, это« как это работает »- подробности см. В блоге Рэймонда Чена https://devblogs.microsoft.com/oldnewthing/20080812-00/?p=21273.
Итераторы C # генерируют очень сложный код.
источник
Ключевое слово yield используется вместе с ключевым словом return для предоставления значения объекту перечислителя. yield return указывает возвращаемое значение или значения. Когда достигается отчет о доходности, текущее местоположение сохраняется. Выполнение возобновляется с этого места при следующем вызове итератора.
Чтобы объяснить значение, используя пример:
Значения, возвращаемые при итерации: 0, 2, 5.
Важно отметить, что переменная counter в этом примере является локальной переменной. После второй итерации, которая возвращает значение 2, третья итерация начинается с того места, где она была ранее, сохраняя предыдущее значение локальной переменной с именем counter, равное 2.
источник
yield break
делаетyield return
самом деле поддерживает возвращение нескольких значений. Может быть, это не то, что вы на самом деле имели в виду, но так я это прочитал.yield break
заключается в том, что он не содержит перечислителя уровня языка, такого какforeach
- при использовании перечислителяyield break
обеспечивает реальное значение. этот пример выглядит как развернутый цикл. вы почти никогда не увидите этот код в реальном мире (мы все можем подумать о некоторых крайних случаях, конечно же), здесь нет итератора. «блок итератора» не может выходить за пределы метода в зависимости от спецификации языка. то, что фактически возвращается, является «перечислимым», см. также: stackoverflow.com/questions/742497/…