LINQ with Console.WriteLine

Мих*_*оев -4 c# linq ienumerable

文件包含一些字符串,如:

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; });
}
Run Code Online (Sandbox Code Playgroud)

此功能不会向控制台输出任何内容.为什么?

Zor*_*vat 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();
}
Run Code Online (Sandbox Code Playgroud)

在相关的说明中,建议不要在LINQ表达式中引起副作用.如果此代码用于调试目的,那么它没关系.但是如果您打算将其保留以备将来使用,那么我建议您Console.Write从LINQ表达式中删除它.

我们不应该在表达式中引起副作用的原因是大多数LINQ运算符都是惰性求值的.反过来,这样做是为了通过仅评估有效请求的序列的那些元素来提高性能.现在,如果评估会产生副作用,那么如果对同一个懒惰序列进行多次评估,这些影响可能会发生几次 - 这可能不是您想要发生的事情.


Ste*_*fan 5

这是延期执行。

只有当您实际枚举结果时,您才会执行该语句。

例如:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

查看其他问题:

C#中的延迟执行

MSDN 示例

LINQ 中的延迟执行有什么好处?

如果您调用 ,也会发生同样的事情F().ToList()

如果枚举本身需要大量资源,则此行为特别有用。有时,底层框架能够在后期优化枚举。

例如,如果您调用以下代码,智能交互器或表达式构建器将能够优化事物:

F().Where(c => ....) 
Run Code Online (Sandbox Code Playgroud)