c# - 什么决定一个变量是否被关闭?

标签 c#

//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/

相关文章:

c# - 在 Unity3D 中使用 Windows.Networking.Sockets

c# - 剪断这个长字符串的最佳方法

c# - 顶点属性缓冲区绑定(bind)到错误的属性

c# - 在 C# wpf 中的 slider 上添加直方图

c# - Dotnet 构建不适用于 newcsproj 和 PackageReference

c# - Autofac 无法解析 ApiController 的类型和命名参数

C# - 如何使用反射调用参数数量可变的静态方法

c# - EF 核心 : Update object graph duplicates child entities

c# - 如何将时间四舍五入到最接近的 X 分钟?

c# - 在读完之前不要关闭 SQL 连接