有趣的行为:带有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查询?如果是,那么这会对性能产生影响吗?最重要的是,我在这里错过了什么吗?
.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