收益率为零

时间:2009-11-19 18:15:19

标签: c#

有没有办法可选地返回带有“return yield”驱动迭代器的null?

我想在某些情况下返回null,我认为这不是特定于IEnumerable类型的字符串。类似于int等的IEnumerable也是如此。谢谢

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.
}

6 个答案:

答案 0 :(得分:39)

如果您需要这样的东西(或立即抛出ArgumentException之类的东西),您需要将迭代器分成两个方法:

 public IEnumerable<string> GetItems() {
     if (something) return null;
     return GetItemsInternal();
 }

 private IEnumerable<string> GetItemsInternal() {
     // the actual iterator with "yield return" goes here.
 }

答案 1 :(得分:30)

您没有按预期使用可枚举(迭代集合中的对象)。如果你想让你的代码与现在的代码类似,你应该这样做:

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

答案 2 :(得分:12)

这不是鼓励。当你谈论一个序列时,“null”通常应该具有与“空列表”相同的语义。

此外,如果没有额外的语法,就不可能将语言设计为以您希望的方式工作,因为如果您点击“yield return [whatever]”然后点击“{{1 }}?“

答案 3 :(得分:6)

无法从迭代器方法中返回null IEnumerable<T>。您可以在迭代器中返回null值,但不能返回null IEnumerable<T>

你可以做的是有一个包装方法,它返回null或调用真正的迭代器

static IEnumerable<string> GetItems() {
    if (false) {
        return GetItemsCore();
    }
    return null;
}

static IEnumerable<string> GetItemsCore() {
    yield return "Andy";
    yield return "Jennifer";
}

答案 4 :(得分:4)

虽然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);
        }

答案 5 :(得分:2)

如果合适(当然,枚举类型必须可以为空),没有什么可以阻止你做yield return null;