//var sample= new { bottom=2, top=5,count=4};
var sample= new [] {2,3,4,5,6};
var q = from x in new int[]{0} //force desired behavior
from i in sample
from j in sample
select Math.Pow(i,j);
q.Distinct().Count().Dump();
sample = new[]{2,3,4,5};
//q = from i in Enumerable.Range(sample.bottom, sample.top-sample.bottom+1)
// from j in Enumerable.Range(sample.bottom, sample.top-sample.bottom+1)
// select checked(System.Numerics.BigInteger.Pow((BigInteger)i,j));
q.Distinct().Count().Dump();
如果 from x line
不存在,或者未完成 q
变量的重置,则每次第二个答案都是不正确的。(此处显示已注释掉)
原始示例是一个匿名变量,但数组也是如此。
var sample = new { bottom =2, top=5};
和这个有关系吗Scope of Linq Expressions defined in a loop - At issue: closing over loop variable ?
为什么在顶部放置一个 1 项数组来修复闭包?
最佳答案
理解这里发生的事情的第一步是理解查询表达式是如何翻译的。根据规范:
from x1 in e1
from x2 in e2
select v
翻译成
e1.SelectMany(x1 => e2, (x1, x2) => v)
理解这一点非常重要。 from x1 in e1 from x2 in e2 select v
的结果是对e1的查询,无论e1
是什么;它是固定的,句号。
现在,问题来了。让我们看看您的查询。
var q = from i in sample
from j in sample
select Math.Pow(i, j)
构造查询时 sample
的值是对数组创建表达式 new[] { 2, 3, 4, 5, 6 的结果的引用}
。让 e1
成为对该数组创建表达式结果的引用。然后查询变为:
e1.SelectMany(i => sample, (i, j) => Math.Pow(i, j));
这是固定的,句号,无论您将什么重新分配给sample
。也就是说,您必须想到
var sample = new[] { 2, 3, 4, 5, 6 }
var q = from i in sample
from j in sample
select Math.Pow(i, j)
作为
var sample = new[] { 2, 3, 4, 5, 6 };
var e1 = sample;
var q = e1.SelectMany(i => sample, (i, j) => Math.Pow(i, j));
现在,sample
结束了,这就是为什么在您为 sample
分配新值后,您会看到不同的查询结果。但是无论如何,作为数组创建表达式new[] { 2, 3, 4, 5, 6 } } 的结果,
.e1
保持不变
但是,当您开始查询时
var q = from x in new int[] { 0 }
from i in sample
from j in sample
select Math.Pow(i, j)
现在查询被翻译成
int[] e1 = new int[] { 0 };
var q = e1.SelectMany(
x1 => sample.SelectMany(i => sample, (i, j) => Math.Pow(i, j)
);
and now sample
被捕获为 i
and j
的序列> 但是 e1
是固定的。
关于c# - 什么决定一个变量是否被关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18029069/