Полезно ли ключевое слово 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
может быть чрезвычайно полезным для более чем обычных коллекций; он также может быть использован для реализации примитивных сопрограмм.