I'm confused about the scope of the lambda variable, take for instance the following
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
};
In line 1 I have declare a lambda variable 'o' which means I cannot declare it again in line 2 (or at least the compiler complains if I try to) But it doesn't complain about line 3 even though 'o1' already exists??
What is the scope of a lambda variable?
When the code is compiled, all the logic from the void declared in the Action
()=>{ ... }
will be moved to a method on the type with a mangled name.The run time will call the newly created function when it is reaches that place on the stack.
You can pass values into a scope / lambda in various ways which is the same for getting them out.
Variables declared in a lambda are not accessible outside with their declared name.
It is also possible to utilize reflection to pull out the mangled name however I am not sure you require that. (Please let me know if I am wrong.)
The brackets give the clue - the lambda variable is captured in the scope of where it's declared:
Note that there's no overlap for the two
o1
variables, but they both overlap (or shadow) theo
variable and hence can't use the same name.The scope of a lambda parameter is equal to the entire scope of the body of the lambda expression, including any inner lambda expressions or scopes.
If we expand the syntax of your lambda expressions and add some friendly indentation it may become clearer (though probably nowhere as clear as yamen's diagrammatic answer!):
Notice that your
.Where().Max()
call is located within an outer.Where()
. Theo
in the outer lambda is encapsulated by the outer lambda within your inner lambdas (this is called closure) such that it exists in the scope of your inner lambdas already, and cannot be reused as a parameter.You can reuse
o1
because your two inner lambdas are completely separate from each other, so it doesn't live beyond the scope of either one.It is the same as with any other variable. The scope of
o
is the whole expression in your firstWhere
, so you cannot use it again in the second, which is inside the first. But the scope ofo1
is just the expression in your secondWhere
, so you can use it in the expression of yourMax
, which is outside the secondWhere
. In the code:becasue lamda is replacement of the anonymous function here in you code
Same Scope
is scope of function in which varialble "o" live
here in line three this is new scrop of the variable i.e new function scope
Different Scope
so that is the reson in line1 and line2 varialbe "o" defined in line1 cannot defined in line2 because of the same scrop and "o1" define in line2 can be defined again in line3 becauase it is in different function scope
C# does not support shadowing like that.
The reason
o1
works again, is that it does not shadow the previouso1
.