为啥 Lambda 变量范围存在于 LINQ 查询之外?
Posted
技术标签:
【中文标题】为啥 Lambda 变量范围存在于 LINQ 查询之外?【英文标题】:Why Lambda variable scope exists outside LINQ Query?为什么 Lambda 变量范围存在于 LINQ 查询之外? 【发布时间】:2012-05-23 07:14:09 【问题描述】:我看了这个问题(What is the scope of a lambda variable in C#?)
但它是关于 LINQ Query 中的 Lambda 变量范围。
现在我的问题
假设我有一个非常简单的 LINQ 查询。
var Foo = FoobBar.Select(x => x);
var x = somefunction();
编译器说:A local variable 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a 'child' scope to denote something else
.
为什么会这样? LINQ 查询结束时,Lambda 变量不应该不复存在吗?
编辑:阅读答案后,我得出结论,它的外部 x
(从函数返回)其范围扩展到 LINQ 查询内部。
【问题讨论】:
在阅读了所有答案后,我得出的结论是反过来。外部变量的范围存在于 LINQ 查询中。 反之亦然 ;-) 如果仅仅因为冲突变量 (var x = somefunction();
) 位于第二行而允许代码编译,则该语言不会对重构友好,然后当您将第二行移到第一行时,令您非常懊恼的是,它将不再编译。 C# 有一个先发制人的机制,它不允许 var x = someFunction()
编译,即使它在第二行,因为您可能随时重构代码并稍后将其放在第一行。我们生活在一个可重构代码成为常态的时代
【参考方案1】:
这与 LINQ 无关,而与子作用域有关。
例如:
foreach (var bar in FooBar.Bars)
var x = FooBar.GetFoo();
var x = new Foo();
从编译器产生完全相同的错误消息。
要解决这个问题,您只需将变量放在不同的(非嵌套)范围内。例如:
foreach (var bar in FooBar.Bars)
var x = FooBar.GetBar();
var x = new Foo();
【讨论】:
【参考方案2】:让我们仔细看看,
var Foo = FoobBar.Select(x => x);
true x 的范围以表达式结尾
var x = somefunction()
现在这很有趣,这也适用于包含 lamda 表达式的整个方法,因此编译器无法区分,因为后者的范围与前者重叠。而且信息也非常丰富赋予“x”不同的含义,它已经在“子”范围内使用 (根据您的情况选择)
Similar scope question
也许你可以在另一个周围包含大括号,以便定义它的范围
var x = somefunction()
【讨论】:
在最后一个sn-p中,这意味着x的范围被限制在那些大括号内?【参考方案3】:想想如果 C# 允许这两个变量存在于同一范围级别,这是不可能的:
static void test()
Action<int> x = (z) =>
Console.WriteLine(z);
;
int[] i = 5,2,0,1,3,1,4 ;
var kyrie = i.Select (x => x);
你会如何对 C# 说你想将名为 x 的 Action 委托分配给 kyrie 变量;反之亦然,你会如何对 C# 说你想使用整数投影本身? C# 将如何解决这个问题?
而且C#的作用域解析是非常一致的,无论你是在其他变量之前还是在其他变量之后声明,它们都是一样的。例如http://www.anicehumble.com/2012/05/java-said-c-said-scope-consistency.html
为了消除这些情况的歧义,C# 不允许您编译具有相同级别的变量名的程序
这一切都是为了以明确的方式向编译器表达您的意图。而 C# 在这方面做得很好
【讨论】:
+1 表示“这一切都是为了以明确的方式向编译器表达你的意图”。完全正确。【参考方案4】:不清楚(编译器)第二个“x”指的是哪个“x”(在=>
之后)。
如果你写这个会怎样:
var Foo = FoobBar.Select(y => x);
var x = somefunction();
那么 lambda 中的 x
将与“somefunction”结果发生冲突。
【讨论】:
【参考方案5】:您不能在同一范围内声明两个具有相同名称的变量。
“相同范围”意味着它们都在当前范围内
void method()
int a;
int a; //wrong!
或者一个在当前范围内,另一个在子范围内。
void method()
int a;
for(;;)
int a; //wrong again!
这是设计使然,适用于任何变量,从 int
s 到 lambda 引用。
【讨论】:
以上是关于为啥 Lambda 变量范围存在于 LINQ 查询之外?的主要内容,如果未能解决你的问题,请参考以下文章