C# 有趣的行为:带整数的LINQ查询
如果我在LINQC# 有趣的行为:带整数的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++) {
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();