Что значит «уступать по размерам»; делать в C #? - PullRequest
447 голосов
/ 24 октября 2008

Я видел этот синтаксис в MSDN: yield break, но я не знаю, что он делает. Кто-нибудь знает?

Ответы [ 10 ]

486 голосов
/ 24 октября 2008

Указывает, что итератор подошел к концу. Вы можете думать о yield break как о return выражении, которое не возвращает значение.

Например, если вы определяете функцию как итератор, тело функции может выглядеть так:

for (int i = 0; i < 5; i++)
{
    yield return i;
}

Console.Out.WriteLine("You will see me");

Обратите внимание, что после того, как цикл завершил все свои циклы, выполняется последняя строка, и вы увидите сообщение в своем консольном приложении.

Или вот так с 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");

В этом случае последний оператор никогда не выполняется, потому что мы рано вышли из функции.

51 голосов
/ 24 октября 2008

Завершает блок итератора (например, говорит, что в IEnumerable больше нет элементов).

29 голосов
/ 24 октября 2008

Сообщает итератору, что он достиг конца.

Как пример:

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;
    }
}
19 голосов
/ 27 июня 2009

yield в основном заставляет метод IEnumerable<T> вести себя подобно кооперативному (в отличие от упреждающего) запланированному потоку.

yield return подобен потоку, вызывающему функцию «schedule» или «sleep» для отказа от управления процессором. Как и поток, метод IEnumerable<T> восстанавливает элементы управления в точке сразу после этого, причем все локальные переменные имеют те же значения, что и до того, как управление было прекращено.

yield break подобен потоку, достигающему конца своей функции и заканчивающемуся.

Люди говорят о "государственном автомате", но конечный автомат - это на самом деле "поток". Поток имеет некоторое состояние (то есть значения локальных переменных), и каждый раз, когда он запланирован, он предпринимает некоторые действия для достижения нового состояния. Ключевым моментом в yield является то, что, в отличие от потоков операционной системы, к которым мы привыкли, код, который его использует, заморожен во времени до тех пор, пока итерация не будет расширена или завершена вручную.

10 голосов
/ 24 октября 2008

Вся тема блоков итераторов хорошо освещена в этой главе бесплатного образца из книги Джона Скита C # in Depth .

7 голосов
/ 04 апреля 2010

Здесь http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/ - очень хороший пример:

public static IEnumerable<int> Range( int min, int max )
{
   while ( true )
   {
      if ( min >= max )
      {
         yield break;
      }
      yield return min++;
   }
}

и объяснение, что если в метод попадает оператор yield break, выполнение этого метода прекращается без возврата. Бывают ситуации, когда вы не хотите давать какой-либо результат, тогда вы можете использовать предел доходности.

5 голосов
/ 26 ноября 2016

Оператор yield break приводит к останову перечисления. По сути, yield break завершает перечисление без возврата каких-либо дополнительных элементов.

Учтите, что на самом деле метод итератора может остановить итерацию двумя способами. В одном случае логика метода могла естественным образом выйти из метода после возврата всех элементов. Вот пример:

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.");
}

В приведенном выше примере метод итератора естественным образом прекратит выполнение, как только будет найдено 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);
        yield return startAt;

        if (sw.Elapsed.TotalMinutes > maxMinutes)
            yield break;
    }

    Debug.WriteLine("All the primes were found.");
}

Обратите внимание на звонок на yield break. По сути, он рано выходит из перечисления.

Обратите внимание, что yield break работает иначе, чем просто break. В приведенном выше примере yield break выходит из метода без вызова Debug.WriteLine(..).

4 голосов
/ 24 октября 2008

Если вы имеете в виду «что действительно дает доходность», это «как это работает» - подробности смотрите в блоге Рэймонда Чена http://blogs.msdn.com/oldnewthing/archive/2008/08/12/8849519.aspx

C # итераторы генерируют очень сложный код.

3 голосов
/ 24 июля 2018

разрыв доходности - это просто способ сказать возврат в последний раз и не возвращать никакого значения

* 1003 например *

// 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;
 }
0 голосов
/ 07 января 2012

Ключевое слово yield используется вместе с ключевым словом return для предоставления значения объекту перечислителя. yield return указывает возвращаемое значение или значения. При достижении отчета о доходности текущее местоположение сохраняется. Выполнение будет возобновлено с этого места при следующем вызове итератора.

Чтобы объяснить значение на примере:

    public IEnumerable<int> SampleNumbers()
    {
        int counter = 0;
        yield return counter;

        counter = counter + 2;

        yield return counter;

        counter = counter + 3;

        yield return counter ;
    }

Значения, возвращаемые при итерации: 0, 2, 5.

Важно отметить, что переменная counter в этом примере является локальной переменной. После второй итерации, которая возвращает значение 2, третья итерация начинается с того места, где она была раньше, при сохранении предыдущего значения локальной переменной с именем counter , равного 2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...