有趣的行为:带有integer的LINQ查询

本文关键字:integer LINQ 带有 查询 | 更新日期: 2023-09-27 18:25:34

如果我在LINQ where子句中使用任何整数变量,并且在执行查询之后,如果我修改/初始化整数变量,那么LINQ查询的结果集将更改。例如:

static void Main(string[] args)
{    
     int startPos = 0;          
     List<string> intList = new List<string>();
     for (int i = 0; i < 10; i++)
     {
        intList.Add(i.ToString());
     }
     var qResult = from c in intList
                   where Convert.ToInt32(c) >= startPos
                   select c;
     // prints count as 10
     Console.WriteLine("List count is :"+qResult.Count());
     startPos = 5;
     // prints count as 5
     Console.WriteLine("List count is :" + qResult.Count());
}

输出:

List count is :10
List count is :5

在上面的例子中,您可以看到startPos = 5;之后,qResult发生了变化。我不明白这是怎么发生的;据我所知,int是值类型。

是否在startPos = 5;行再次执行Linq查询?如果是,那么这会对性能产生影响吗?最重要的是,我在这里错过了什么吗?

有趣的行为:带有integer的LINQ查询

每次调用.Count()时,

qResult都会被枚举,因此当您在对.Count()的调用之间更改startPos时,实际上是在更改正在执行的代码。

为了避免这种情况,请通过调用.ToList().ToArray()或类似程序来枚举您的列表一次:

List<string> qResult = (from c in intList
                   where Convert.ToInt32(c) >=startPos
                   select c).ToList();

这是一篇关于LINQ中延迟执行的非常好的文章。

这是因为qResult将是IEnumerable<T>,每次调用.Count()时都会执行。如果你想让结果永远不会改变,只需像这样使用ToList()

var qResult = (from c in intList
               where Convert.ToInt32(c) >=startPos
               select c).ToList();

.Count()在调用时执行枚举。它不像是一个可变值,因此结果与预期行为一致。

linq查询在调用时执行,因为它使用延迟加载,在您的情况下,如果您希望强制执行调用ToList()或类似函数

,则查询在qResult.Count()中执行

是的,这是因为每次调用Count()时都会枚举qResult,并且您正在访问linq查询中的修改的闭包。您应该使用第三个变量来避免这种行为:

        int pos = startPos;
        var qResult = from c in intList
                      where Convert.ToInt32(c) >= pos
                      select c;

或枚举到位:

        var qResult = (from c in intList
                      where Convert.ToInt32(c) >= startPos
                      select c).ToArray();

它被称为deffered execution