Полезно ли ключевое слово yield вне блока итераторов?

yield Документация по ключевым словам гласит:

Ключевое слово yield сообщает компилятору, что метод, в котором он появляется, является блоком итератора.

Я столкнулся с кодом, использующим yield Ключевое слово вне любого блока итератора. Должно ли это быть ошибкой программирования или это нормально?

РЕДАКТИРОВАТЬ К сожалению забыл опубликовать мой код:

int yield = previousVal/actualVal;
return yield; // Should this be allowed!!!???

Благодарю.

3 ответа

Решение

Это нормально использовать yield вне блока итератора - это просто означает, что он не используется в качестве контекстного ключевого слова.

Например:

// No idea whether this is financially correct, but imagine it is :)
decimal yield = amountReturned / amountInvested;

В этот момент это не контекстное ключевое слово (это никогда не "полное" ключевое слово), это просто идентификатор. Если это явно не лучший выбор с точки зрения нормальной ясности, я все равно стараюсь не использовать его, но иногда это может быть.

Вы можете использовать его только как контекстное ключевое слово для yield return а также yield break, которые действительны только в блоке итератора. (Именно они превращают метод в итератор.)

РЕДАКТИРОВАТЬ: Чтобы ответить на ваш вопрос "это должно быть разрешено"... да, это должно. В противном случае весь существующий код C# 1, который использовал yield как идентификатор стал бы недействительным, когда C# 2 был выпущен. Его следует использовать с осторожностью, и команда C# позаботилась о том, чтобы он никогда не был неоднозначным, но имеет смысл, чтобы он был действительным.

То же самое относится ко многим другим контекстным ключевым словам - "от", "выберите", "где" и т. Д. Хотели бы вы, чтобы они никогда не были идентификаторами?

Что это говорит о том, что если вы используете yield в методе метод становится блоком итератора.

Также как yield является контекстным ключевым словом, которое может свободно использоваться в другом месте, где полные ключевые слова не могут (например, имена переменных).

void AnotherMethod()
{
    foreach(var NotRandomNumber in GetNotVeryRandomNumbers())
    {
        Console.WriteLine("This is not random! {0}", NotRandomNumber);
    }
}

IEnumerable<int> GetNotVeryRandomNumbers()
{
    yield return 1;
    yield return 53;
    yield return 79;
    yield return 1;
    yield return 789;
}

// Perhaps more useful function below: (untested but you get the idea)
IEnumerable<Node> DepthFirstIteration(Node)
{
    foreach(var Child in Node.Children)
    {
        foreach(var FurtherChildren in DepthFirstIteration(Child))
        {
            yield return FurtherChildren;
        }
    }
    yield return Node;
}

Смотрите также: Этот ответ, который показывает использование одного урожая за другим. Умное использование блоков итераторов

yield это контекстное ключевое слово.
Когда используется в yield return или же yield break, это ключевое слово и создает итератор.
Когда используется в другом месте, это нормальный идентификатор.

yield может быть чрезвычайно полезным для более чем обычных коллекций; он также может быть использован для реализации примитивных сопрограмм.

Другие вопросы по тегам