Что делает "yield break;" в C#?


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

10 417

10 ответов:

он указывает, что итератор подошел к концу. Вы можете думать о 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");

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

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

указывает итератор, достиг конца.

в качестве примера:

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

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

yield break это как нить, достигающая конца своя функция и прекращать.

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

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

здесь 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++;
   }
}

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

The 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 простые числа были найдены.

The 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(..).

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

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

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

Эл.г

// 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;
 }

ключевое слово 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.

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