我感到困惑λ变量的范围,就拿下面
var query =
from customer in clist
from order in olist
.Where(o => o.CustomerID == customer.CustomerID && o.OrderDate == // line 1
olist.Where(o1 => o1.CustomerID == customer.CustomerID) // line 2
.Max(o1 => o1.OrderDate) // line 3
)
select new {
customer.CustomerID,
customer.Name,
customer.Address,
order.Product,
order.OrderDate
};
在1号线我有声明λ变量的“o”,这意味着我不能在2号线再次声明(或至少编译器会抱怨,如果我尝试),但它并没有抱怨3号线,即使“01”已存在??
什么是λ变量的范围是什么?
Answer 1:
括号给的线索 - λ变量是在它的声明,其中的范围捕获:
.Where(o => ... olist.Where(o1 => ...).Max(o1 => ...))
// |----------------------------------------------| scope of o
// |---------| scope of first o1
// |---------| scope of second o1
请注意,有两个没有重叠o1
变量,但他们都重叠(或阴影)的o
变量,因此不能使用相同的名称。
Answer 2:
的λ参数的范围是等于lambda表达式的主体中,包括任何内lambda表达式或范围的整个范围。
如果我们扩大你的lambda表达式的语法,并添加一些友好的缺口可能会清晰一些(尽管可能无处为清晰衙门的图解答案 !):
.Where(o => {
return o.CustomerID == customer.CustomerID
&& o.OrderDate == olist.Where(
o1 => o1.CustomerID == customer.CustomerID
)
.Max(
o1 => o1.OrderDate
);
})
请注意,您的.Where().Max()
调用位于外内.Where()
该o
在外拉姆达由您内lambda表达式内的外的λ封装(这被称为闭合 ),从而使得它在你的内lambda表达式的范围中已经存在,并且不能被重新使用作为参数。
您可以重复使用o1
因为你的两个内部lambda表达式是彼此完全独立的,所以它不会活过任何一个的范围。
Answer 3:
如果将作用域的一个包含其他不能在两个作用域使用相同的变量名。
在你的问题, o
在外部范围推出,所以它不能在第二次再次使用Where()
或Max()
因为这些范围都包含在外层一个。
在另一方面,你可以使用o1
在两个内部范围,因为一个不包含其他的,所以没有歧义存在。
Answer 4:
becasue LAMDA是更换匿名函数在这里你的代码
相同的范围内
Where(o => o.CustomerID == customer.CustomerID && o.OrderDate == //line 1
olist.Where(o1 => o1.CustomerID == customer.CustomerID) //line 2
是的功能范围,其中varialble“O”活
这里三线,这也就是新的功能范围变量的新scrop
不同的适用范围
.Max(o1 => o1.OrderDate) ) //line 3
使得在第1行所定义的第1行和第2行varialbe“○”的RESON不能LINE2定义的,因为相同的scrop和“01”定义LINE2 becauase它是在不同的功能范围,可以在再次line3中的定义
Answer 5:
C#不支持阴影那样。
究其原因o1
再次工作,是它不影之前的o1
。
Answer 6:
这是相同的,与任何其它变量。 范围o
是你的第一个整个表达式Where
,所以你不能在第二,这是第一个内再次使用它。 但是范围o1
是刚刚在你的第二个表达Where
,这样你就可以在你的表达式中使用Max
,这是外面的第二Where
。 在代码:
// o scope lasts until the first bracket is closed
Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==
// o1 scope lasts until the second bracket is closed; the first is not yet closed here
olist.Where(o1 => o1.CustomerID == customer.CustomerID)
// The second bracket is closed, so o1 is already out of scope; o is still in scope
.Max(o1 => o1.OrderDate)
)
// The first bracket is closed, so o is finally out of scope
Answer 7:
我试着想象像这样按你的代码...
.Where(o => o.CustomerID == customer.CustomerID && o.OrderDate == // line 1
olist.Where(o1 => o1.CustomerID == customer.CustomerID) // line 2
.Max(o1 => o1.OrderDate) // line 3
)
解释,但你的括号确定的范围,而粗暴的方式。 你的第二O1没有嵌套在第二个地方,其他明智的你有同样的问题里面
//outermost where
((BEGIN-o
//inner where
(BEGIN-o1 END-o1)
//max
(BEGIN-o1 END-o1)
END-o))
Answer 8:
var external = 1;
//This is a scope
Action scope = new Action(() =>
{
//myVar is not accessible from outside
var myVar = 0 + external;
Console.WriteLine(myVar); //outputs 1
});
//Call the scope
scope();
//Console.WriteLine(myVar);//Will not compile
当代码被编译,所有从空隙中的逻辑在Action声明()=>{ ... }
将被移动到在具有重整名称的类型的方法。
运行时间将调用新创建的功能时,它达到堆栈上那个地方。
您可以通过值成以各种方式范围/λ这是让他们出来的一样。
在一个lambda声明的变量是无法访问外与他们的声明的名称。
也可以利用反射拉出重整名称但我不知道你需要。 (请让我知道,如果我错了。)
文章来源: What is the scope of a lambda variable in C#?