leo*_*ora 7 c# ienumerable iterator yield
仍然试图找到我在实际情况下使用"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
语句时会"暂停" .
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)