Lambda capture parameter is ambiguous

I just ran into really weird C # behavior and Id would be glad if anyone could explain this to me.

Let's say I have the following class:

class Program { static int len = 1; static void Main(string[] args) { Func<double, double> call = len => 1; len = 1; // error: 'len' conflicts with the declaration 'csutils.Program.len' Program.len = 1; // ok } } 

As I understand it, in the comment line I have the following objects in my field of view: len variable and call . Inside lambda, I have a local parameter parameter len and Program.len .

However, after declaring such a lambda, I can no longer use the len variable in the Main . I have to either reference it, or Program.len or rewrite lambda as anyOtherNameBesidesLen => 1 .

Why is this happening? Is this the correct language behavior, or has Ive encountered a language error? If this is correct behavior, how is language architecture justifying it? Why is it ok for a lambda capture variable to work with code outside of lambda?

Edit: Alessandro D'Andria has some good examples (number 1 and 2 in his comment).

edit2: This code (equal to the one I wrote at the beginning) is illegal:

 class Program { static int len = 0; static void Main(string[] args) { { int len = 1; } int x = len; } } 

This code, although it has exactly the same visibility structure, is completely legal:

 class Other { static int len = 0; class Nested { static void foo() { int len = 1; } static int x = len; } } 
+7
c # lambda
source share
2 answers

As far as I can tell, it is correct to correct the compile-time error in this case, because it is unacceptable to use len in a child region (namely, an anonymous function parameter (lambda)) when the same len character is used without qualification (for something else) in the region content inside the same method.

However, the error text is confused.

If you change to:

 static int len = 1; static void Main(string[] args) { len = 1; Func<double, double> call = len => 1; // error CS0136: A local variable named 'len' cannot be declared in this scope because it would give a different meaning to 'len', which is already used in a 'parent or current' scope to denote something else } 

error text is better.


Some other examples:

 static int len = 1; static void Main() { var len = 3.14; // OK, can hide field Console.WriteLine(len); // OK, 'len' refers to local variable Console.WriteLine(Program.len); // OK, hidden field can still be accessed, with proper qualification } 

The above example shows that to hide a local value (or method parameter) with the same name, if the field is always available with qualifications (after the access operator to the element . ), It’s fine to hide.

 static int len = 1; static void Main() { if (DateTime.Today.DayOfWeek == DayOfWeek.Saturday) { var len = 3.14; Console.WriteLine(len); } Console.WriteLine(len); // error CS0135: 'len' conflicts with the declaration 'csutils.Program.len' } 

This shows that it is not possible to hide len in the child scope when you try to use the len field in the parent scope. Again, the error text may be criticized.

 static int len = 1; static void Main() { Console.WriteLine(len); if (DateTime.Today.DayOfWeek == DayOfWeek.Saturday) { var len = 3.14; // error CS0136: A local variable named 'len' cannot be declared in this scope because it would give a different meaning to 'len', which is already used in a 'parent or current' scope to denote something else Console.WriteLine(len); } } 

You see an analogy.


Of course, these problems have been mentioned many times before here on SO, an example of which is Why can't a duplicate variable name be declared in a nested local scope?

+4
source share

The error message is erroneous and should point to a string containing lambda.

As you say, “Inside the lambda, I have a local parameter len and Program.len variable”, the problem is that the parameter name of the lambda conflicts with the variable len . Thus, the problem is only in the lambda expression. The problem is not that you "can no longer use the len variable in the Main scope"). This is a conflict between the two, and no code will compile at all anymore.

0
source share

All Articles