我对lambda变量的范围感到困惑,例如以下内容
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
};
Run Code Online (Sandbox Code Playgroud)
在第1行中,我声明了一个lambda变量'o',这意味着我不能在第2行再次声明它(或者至少编译器在我尝试时会抱怨)但是即使'o1'已经存在,它也不会抱怨第3行??
lambda变量的范围是什么?
yam*_*men 174
括号给出了线索 - lambda变量在声明它的范围内捕获:
.Where(o => ... olist.Where(o1 => ...).Max(o1 => ...))
// |----------------------------------------------| scope of o
// |---------| scope of first o1
// |---------| scope of second o1
Run Code Online (Sandbox Code Playgroud)
请注意,两个o1
变量没有重叠,但它们都重叠(或隐藏)o
变量,因此不能使用相同的名称.
Bol*_*ock 14
lambda参数的范围等于lambda表达式主体的整个范围,包括任何内部lambda表达式或范围.
如果我们扩展lambda表达式的语法并添加一些友好的缩进,它可能会变得更清晰(尽管可能没有yamen的图解答案那么明确!):
.Where(o => {
return o.CustomerID == customer.CustomerID
&& o.OrderDate == olist.Where(
o1 => o1.CustomerID == customer.CustomerID
)
.Max(
o1 => o1.OrderDate
);
})
Run Code Online (Sandbox Code Playgroud)
请注意,您的.Where().Max()
呼叫位于外部.Where()
.的o
在外部的λ是由您内lambda表达式内的外的λ封装(这被称为闭合),从而使得它在你的内lambda表达式的范围中已经存在,并且不能被重新使用作为参数.
您可以重复使用,o1
因为您的两个内部lambda彼此完全分离,因此它不会超出任何一个范围.
如果其中一个范围包含另一个范围,则不能在两个范围中使用相同的变量名称.
在您的问题中,o
是在外部范围中引入的,因此它不能在第二个Where()
或中使用Max()
,因为这些范围包含在外部范围内.
另一方面,您可以o1
在两个内部范围中使用,因为一个不包含另一个范围,因此没有歧义.