foreach只执行一次查询吗?

Mar*_*cel 20 c# linq tolist

我有一个项目列表和LINQ查询.现在,使用LINQ的延迟执行,后续的foreach循环是否只执行一次查询或循环中的每次转弯?

给出这个例子(取自LINQ查询简介(C#),在MSDN上)

    // The Three Parts of a LINQ Query: 
    //  1. Data source. 
    int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

    // 2. Query creation. 
    // numQuery is an IEnumerable<int> 
    var numQuery =
        from num in numbers
        where (num % 2) == 0
        select num;

    // 3. Query execution. 
    foreach (int num in numQuery)
    {
        Console.Write("{0,1} ", num);
    }
Run Code Online (Sandbox Code Playgroud)

或者,换句话说,如果我有以下情况会有什么不同:

    foreach (int num in numQuery.ToList())
Run Code Online (Sandbox Code Playgroud)

而且,如果底层数据不在数组中,而是在数据库中,这是否重要?

Jon*_*nna 19

现在,使用LINQ的延迟执行,后续的foreach循环是否只执行一次查询或循环中的每次转弯?

是的,一次循环.实际上,它可能不到一次执行查询 - 您可以中止循环部分,并且(num % 2) == 0不会对任何剩余项执行测试.

或者,换句话说,如果我有以下情况会有什么不同:

foreach (int num in numQuery.ToList())
Run Code Online (Sandbox Code Playgroud)

两个区别:

  1. 在上面的例子中,ToList()浪费时间和内存,因为它首先做与初始相同的事情foreach,从它构建一个列表,然后foreach是那个列表.根据结果​​的大小,差异将介于微不足道和防止代码工作之间.

  2. 但是,如果您要重复执行foreach相同的结果,或者反复使用它,那么当foreach只运行查询一次时,下foreach一次再次运行它.如果查询很昂贵,那么ToList()方法(并存储该列表)可以节省大量资金.


Mar*_*tos 9

不,它没有任何区别.该in表达式评估一次.更具体地说,foreach构造调用表达式GetEnumerator()上的方法in并重复调用MoveNext()和访问Current属性以遍历表达式IEnumerable.

OTOH,呼叫ToList()是多余的.你不应该打扰它.

如果输入是一个数据库,情况会略有不同,因为LINQ输出IQueryable,但我很确定它foreach仍将它视为IEnumerable(IQueryable继承).