收益率关键字增值?

leo*_*ora 7 c# ienumerable iterator yield

仍然试图找到我在实际情况下使用"yield"关键字的位置.

我在这个主题上看到了这个主题

C#中使用的yield关键字是什么?

但是在接受的答案中,他们将此作为一个例子,其中某人正在迭代Integers()

public IEnumerable<int> Integers()
{
yield return 1;
yield return 2;
yield return 4;
yield return 8;
yield return 16;
yield return 16777216;
}
Run Code Online (Sandbox Code Playgroud)

但为什么不用

list<int>
Run Code Online (Sandbox Code Playgroud)

在这里.似乎更直截了当..

Dan*_*ker 23

如果你构建并返回一个List(比如它有100万个元素),那就是一大块内存,也是创建它的工作.

有时调用者可能只想知道第一个元素是什么.或者他们可能希望在获取文件时将它们写入文件,而不是在内存中构建整个列表,然后将其写入文件.

这就是为什么使用收益率回报更有意义.它与构建整个列表并返回它看起来并没有什么不同,但它是非常不同的,因为在调用者可以查看其上的第一个项目之前,不必在内存中创建整个列表.

当来电者说:

foreach (int i in Integers())
{
   // do something with i
}
Run Code Online (Sandbox Code Playgroud)

每次循环需要一个新的i时,它会在Integers()中运行更多的代码.该函数中的代码在命中yield return语句时会"暂停" .


ang*_*son 9

Yield允许您构建生成数据的方法,而无需在返回之前收集所有内容.将其视为沿途返回多个值.

以下是一些说明这一点的方法

public IEnumerable<String> LinesFromFile(String fileName)
{
    using (StreamReader reader = new StreamReader(fileName))
    {
        String line;
        while ((line = reader.ReadLine()) != null)
            yield return line;
    }
}

public IEnumerable<String> LinesWithEmails(IEnumerable<String> lines)
{
    foreach (String line in lines)
    {
        if (line.Contains("@"))
            yield return line;
    }
}
Run Code Online (Sandbox Code Playgroud)

这两种方法都不会将文件的全部内容读入内存,但您可以像这样使用它们:

foreach (String lineWithEmail in LinesWithEmails(LinesFromFile("test.txt")))
    Console.Out.WriteLine(lineWithEmail);
Run Code Online (Sandbox Code Playgroud)