2

我试图了解使用 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

4 回答 4

8

Usingyield return i使这个方法成为一个迭代器。它将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>自定义类型通常需要创建自定义类等。在迭代器之前,这需要大量代码,如在 C# 中实现自定义集合的旧示例中所示。

于 2013-02-15T17:54:54.020 回答
2

正如 Reed 所说, usingyield允许您实现迭代器。迭代器的主要优点是它允许惰性求值。即,除非需要,否则不必实现整个结果。

Consider Directory.GetFiles from the BCL. It returns string[]. I.e. it has to get all the files and put the names in an array before it returns. In contrast Directory.EnumerateFiles returns IEnumerable<string>. I.e. the caller is responsible for handling the result set. That means that the caller can opt out of enumerating the collection at any point.

于 2013-02-15T18:00:50.633 回答
1

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

yield return语句不只是退出函数并返回一个值,它使代码处于一种状态,以便在从枚举器请求下一个值时可以在该点恢复。

于 2013-02-15T17:59:00.323 回答
1

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

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

于 2013-02-15T17:59:08.837 回答