Подтвердить что ты не робот

Возврат урожая с нулевым

Можно ли возвращать нуль с помощью итератора с возвратным выходом?

Я хотел бы вернуть 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.
}
4b9b3361

Ответ 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).