文件包含一些字符串,例如:
abc 4 2
def 1 1 1
Gh 0
有一些LINQ功能, 这个功能的细节并不那么重要
IEnumerable<List<int>> F() {
return File.ReadLines("input.txt")
.Select(a => a.Split(' ').Skip(1).Select(int.Parse).ToList())
.Where(a => a.Count >= 2)
.Take(3).OrderBy(a => a.Sum())
.Select(a => { Console.Write(a[0]); return a; });
}
此功能不会向控制台输出任何内容。 为什么呢?
答案 0 :(得分:6)
您必须具体化序列才能使其运行:
IEnumerable<List<int>> F() {
return File.ReadLines("input.txt")
.Select(a => a.Split(' ').Skip(1).Select(int.Parse).ToList())
.Where(a => a.Count >= 2)
.Take(3).OrderBy(a => a.Sum())
.Select(a => { Console.Write(a[0]); return a; })
.ToList();
}
相关说明,建议不要在LINQ表达式中引起副作用。如果此代码用于调试目的,那么它没关系。但是如果你打算将它留待将来使用,那么我建议你从LINQ表达式中删除Console.Write
。
我们不应该在表达式中引起副作用的原因是大多数LINQ运算符都是惰性求值的。反过来,这样做是为了通过仅评估有效请求的序列的那些元素来提高性能。现在,如果评估会产生副作用,那么如果对同一个懒惰序列进行多次评估,这些影响可能会发生几次 - 这可能不是您想要发生的事情。
答案 1 :(得分:4)
这是延迟执行。
只有您实际枚举结果时才会执行语句。
例如:
IEnumerable<List<int>> F() {
return File.ReadLines("input.txt")
.Select(a => a.Split(' ').Skip(1).Select(int.Parse).ToList())
.Where(a => a.Count >= 2)
.Take(3).OrderBy(a => a.Sum())
.Select(a => { Console.Write(a[0]); return a; });
}
void Main()
{
foreach(var r in F()) //the result is enumerated and will execute the select
{
//do stuff
}
}
见其他问题:
What are the benefits of a Deferred Execution in LINQ?
如果你打电话给F().ToList()
,也会发生同样的事情。
如果枚举本身需要大量资源,则此行为尤其有用。有时,底层框架能够在稍后阶段优化枚举。
例如,如果您要调用以下内容,智能交互操作员或表达式构建器将能够优化:
F().Where(c => ....)