为什么 Lambda 变量作用域存在于 LINQ 查询之外
本文关键字:LINQ 查询 存在 Lambda 变量 作用域 为什么 | 更新日期: 2023-09-27 18:35:06
我读了这个问题(C#中lambda变量的作用域是什么?
但它是关于 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 Query内部。
这与 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();
}
让我们仔细看看,
var Foo = FoobBar.Select(x => x);
true x 的范围在表达式中结束
var x = somefunction()
现在这很有趣,这也是包含 lamda 表达式的整个方法的范围,因此编译器无法区分,因为后者的范围与前者重叠。 并且信息量很大的消息也为"x"赋予了不同的含义,该含义已在"子"范围内使用(根据您的情况选择)
类似范围问题
也许您可以在另一个周围包含大括号,以便定义其范围
{
var x = somefunction()
}
想想如果 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#在这方面做得很好
不清楚(对编译器来说)第二个"x"(在=>
之后)指的是哪个"x"。
如果你写这个:
var Foo = FoobBar.Select(y => x);
var x = somefunction();
然后,lambda 中的x
将与"某个函数"结果发生冲突。
不能在同一作用域中声明两个同名变量。
"相同范围"意味着它们都在当前范围内
void method()
{
int a;
int a; //wrong!
}
或者一个在当前范围内,另一个在子作用域中。
void method()
{
int a;
for(;;)
{
int a; //wrong again!
}
}
这是设计使然,适用于从 int
s 到 lambda 引用的任何变量。