Возврат урожая с нулевым
Можно ли возвращать нуль с помощью итератора с возвратным выходом?
Я хотел бы вернуть null в некоторых случаях, и я не думаю, что это относится к IEnumerable строки типа. То же самое касается IEnumerable типа int и т.д. Спасибо.
static void Main(string[] args)
{
var Items = GetItems();
if (Items != null)
{
foreach (var item in Items)
{
Console.WriteLine(item);
}
}
else
{
Console.WriteLine("<null>");
}
}
static IEnumerable<string> GetItems()
{
if (false)
{
yield return "Andy";
yield return "Jennifer";
}
return null; // <- Compiler Error:
// Cannot return a value from an iterator.
// Use the yield return statement to return a value,
// or yield break to end the iteration.
}
Ответы
Ответ 1
Если вам нужно что-то подобное (или сразу бросайте такие вещи, как ArgumentException
), вам нужно отделить ваш итератор двумя способами:
public IEnumerable<string> GetItems() {
if (something) return null;
return GetItemsInternal();
}
private IEnumerable<string> GetItemsInternal() {
// the actual iterator with "yield return" goes here.
}
Ответ 2
Вы не используете перечислимое, как предполагалось (для итерации объектов в коллекции). Если вы хотите, чтобы ваш код был похож на то, что он сейчас, вы должны сделать что-то вроде этого:
static void Main(string[] args)
{
var Items = GetItems();
foreach (var item in Items) //this will not enter the loop because there are no items in the Items collection
{
Console.WriteLine(item);
}
//if you still need to know if there were items, check the Count() extension method
if(Items.Count() == 0)
{
Console.WriteLine("0 items returned");
}
}
static IEnumerable<string> GetItems()
{
if (false)
{
yield return "Andy";
yield return "Jennifer";
}
yield break;
}
Ответ 3
Это просто не рекомендуется. Когда вы говорите о последовательности, "null" обычно должен иметь ту же семантику, что и "пустой список".
Кроме того, невозможно создать язык для работы так, как вы хотите, чтобы он работал здесь без дополнительного синтаксиса, так как если бы вы попали в "yield return [whatever]
", а затем "return null
?"
Ответ 4
Невозможно вернуть null IEnumerable<T>
из метода итератора. Вы можете вернуть нулевые значения в итераторе, но не null IEnumerable<T>
Что бы вы могли сделать, это иметь метод-обертку, который либо возвращает null, либо вызывает действительный итератор
static IEnumerable<string> GetItems() {
if (false) {
return GetItemsCore();
}
return null;
}
static IEnumerable<string> GetItemsCore() {
yield return "Andy";
yield return "Jennifer";
}
Ответ 5
В то время как yield break
является наилучшим ответом, и это действительно не имеет значения, поскольку вы всегда можете сделать Items.Count()
, чтобы проверить, имеет ли больший ноль или даже сделать for each on your empty result
, ситуации, в которых это имеет значение, если ваш результат является пустой список или ничего вообще, и вы все еще хотите использовать силу урожая.
В этом случае это поможет.
private IEnumerable<T> YieldItems<T>(IEnumerable<T> items, Action empty = null)
{
if (items == null)
{
if (empty != null) empty();
yield break;
}
foreach (var item in items)
{
yield return item;
}
}
Использование
foreach (var item in YieldItems<string>(null, () =>
{
Console.WriteLine("Empty");
}))
{
Console.WriteLine(item);
}
Ответ 6
Нет ничего, что помешало бы вам выполнить yield return null;
, если это уместно (конечно, нумерованный тип должен иметь значение NULL).