C# 有趣的行为:带整数的LINQ查询

C# 有趣的行为:带整数的LINQ查询,c#,linq,C#,Linq,如果我在LINQwhere子句中使用任何整数变量,并且在查询执行后如果我修改/初始化整数变量,那么LINQ查询的结果集将更改。例如: static void Main(string[] args) { int startPos = 0; List<string> intList = new List<string>(); for (int i = 0; i < 10; i++) {

如果我在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());
}
在上面的示例中,您可以看到在
startPos=5
qResult
已更改。我不明白这是怎么发生的;据我所知,
int
是值类型

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

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

要避免这种情况,请通过调用
.ToList()
.ToArray()
或类似方法枚举列表一次:

List<string> qResult = (from c in intList
                   where Convert.ToInt32(c) >=startPos
                   select c).ToList();
List qResult=(来自intList中的c
其中Convert.ToInt32(c)>=startPos
选择c.ToList();

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

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

linq查询在调用时执行,因为它使用延迟加载,在您的情况下,如果您希望强制执行调用
ToList()
,或类似的函数,您的查询将在
qResult.Count()
中执行,这是因为每次调用
Count()
并访问修改后的linq查询时,都会枚举
qResult
。应使用第三个变量来避免此行为:

        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();

它被称为差异执行,这是因为
qResult
将是一个
IEnumerable
,每次调用
.Count()
时都会执行。如果希望结果永远不变,只需像这样使用
ToList()

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

不同的执行:)只需使用
.ToList()
来阻止它。查询是在获取数据时执行的,而不是在写入
Where
子句时执行的。的可能重复项和许多其他项。您应该仔细阅读闭包:。一旦你理解了它们,它们就相当整洁了。就像乌兹克说的,这是不同的诠释。换句话说,这是正常的行为。当您进行查询时,它不会被执行。只有当您实际需要数据时,才会执行example@Chips_100好的观点,更新的答案来澄清。
var qResult = (from c in intList
               where Convert.ToInt32(c) >=startPos
               select c).ToList();