Why does my parameter x
behave so erratically?
x
because it's defined in a 'child' scope.Example 1:
List<int> list = new List<int> { 1, 2, 3, 4, 5 }; var result = list.Where(x => x < 3); Console.Write(result.ElementAt(x));
creates this compile time error:
The name 'x' does not exist in the current context
which I expect.
Example 2:
List<int> list = new List<int> { 1, 2, 3, 4, 5 }; var result = list.Where(x => x < 3); int x = 1; Console.Write(result.ElementAt(x));
produces this compile-time error:
A local variable named '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
I understand the scoping as answered in this question, Is there a reason for C#'s reuse of the variable in a foreach?. However, this is something I've never seen before. In addition, it makes the answers to this question, What is the scope of a lambda variable in C#?, incomplete or wrong.
Example 3:
List<int> list = new List<int> { 1, 2, 3, 4, 5 }; List<string> stringList = new List<string> { "A", "B" }; var result = list.Where(x => x < 3); var result2 = stringList.Where(x => x != "A"); Console.Write(result2);
No errors produced.
declaration space
simple names
1 Scope of a Lambda Expression. The body of a lambda expression has the same scope as a nested block. The same rules for name conflicts and shadowing apply. It is illegal to declare a parameter or a local variable in the lambda that has the same name as a local variable.
The context of a lambda is the set of objects that are in scope when the lambda is called. The context objects may be captured then used as part of the lambda's processing. Capturing an object by name makes a lambda-local copy of the object. Capturing an object by reference allows the lambda to manipulate its context.
In C#, the capability that allows a method or a function to reference a non-local variable or value is called closure.
In Example 1
, x is defined in the local scope of the lamdba expression and is not visible to the third line
In Example 2
, now you've declared two variables named "x" at the same declaration scope (visibility is different)
With a lambda or anonymous method, it "captures" the scope at which it is running. If you have a local x in the same scope as the lambda definition, then it "captures" that x to pull into what the lambda can access--thus resulting in two definitions of "x". What you declare in the lambda doesn't get captured in the other direction so it isn't visible outside the lambda.
In Example 3
, Now you're not using a variable that is local only the lambda outside the lambda, and not naming something the same at the same declaration scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With