为什么选择收益而不是简单的收益?

时间:2013-02-15 17:54:04

标签: c#

我试图了解使用Yield来枚举集合。我写了这个基本代码:

static void Main(string[] args)
{
    Iterate iterate = new Iterate();
    foreach (int i in iterate.EnumerateList())
    {
        Console.Write("{0}", i);
    }
    Console.ReadLine();
}

class Iterate
{
    public IEnumerable<int> EnumerateList()
    {
        List<int> lstNumbers = new List<int>();

        lstNumbers.Add(1);
        lstNumbers.Add(2);
        lstNumbers.Add(3);
        lstNumbers.Add(4);
        lstNumbers.Add(5);

        foreach (int i in lstNumbers)
        {
            yield return i;
        }
    }
}

(1)如果我只使用return i代替yield return i怎么办?

(2)使用Yield有什么好处,何时更喜欢使用它?

已编辑**

在上面的代码中,我认为使用foreach两次是一种开销。首先是main function,第二个是EnumerateList方法。

4 个答案:

答案 0 :(得分:8)

使用yield return i使此方法成为iterator。它将从整个循环中创建一个IEnumerable<int>值序列。

如果您使用return i,则只返回一个int值。在您的情况下,这会导致编译器错误,因为您的方法的返回类型是IEnumerable<int>,而不是int

在这个具体的例子中,我个人只返回lstNumbers而不是使用迭代器。但是,您可以在没有列表的情况下重写此内容,如:

public IEnumerable<int> EnumerateList()
{
    yield return 1;
    yield return 2;
    yield return 3;
    yield return 4;
    yield return 5;
}

甚至:

public IEnumerable<int> EnumerateList()
{
    for (int i=1;i<=5;++i)
        yield return i;
}

当你创建一个你想要像集合一样的课时,这非常方便。手动为自定义类型实现IEnumerable<T>通常需要创建自定义类等。在迭代器之前,这需要大量代码,如old sample for implementing a custom collection in C#所示。

答案 1 :(得分:2)

正如Reed所说,使用yield可以实现迭代器。迭代器的主要优点是它允许延迟评估。即除非需要,否则它不必实现整个结果。

从BCL考虑Directory.GetFiles。它返回string[]。即它必须获取所有文件并在返回之前将名称放在数组中。相比之下,Directory.EnumerateFiles会返回IEnumerable<string>。即调用者负责处理结果集。这意味着调用者可以在任何时候选择不再枚举集合。

答案 2 :(得分:1)

yield关键字将使编译器将函数转换为枚举器对象。

yield return语句不会简单地退出函数并返回一个值,它会使代码保持一个状态,以便在从枚举器请求下一个值时可以恢复该代码。

答案 3 :(得分:1)

你不能只返回我,因为我是一个int而不是IEnumerable。它甚至不会编译。您可以返回lstNumbers,因为它实现了IEnumerable的接口。

我更喜欢yield return,因为编译器将处理构建可枚举的内容而不必首先构建列表。所以对我来说,如果我有一些已经在实现接口的东西,那么我返回,如果我必须构建它而不是使用它,那么我产生返回。