开发者

C# LINQ/Lambda scope question

I get the error :

A local variable named 's' cannot be declared in this scope because it would give a different meaning to 's', which is already used in a 'child' scope to denote something else.

static void Main(string[] args)
{
    string s = "hello"; // Line 1
    var tes开发者_StackOverflow中文版t = new[] { "abd", "def" }.Select(s => s.StartsWith("a")); // Line 2
}

Why?

I would have guessed that the 's' from line 1 would be shaded by the '.Select(s =>..' decleration in line 2 but - as far as I can tell - this is not the case..

PS I'm not sure that shaded it the proper term - please correct me if a better word/phrase exsists.


You get an error for the same reason that in a normal code block (like an if statement or loop), you cannot declare variables with the same name as outside the code block.

This is different than for class variables and method variables, where you can explicitly reference class variables with the this keyword.

I think that the this keyword is the key, as there isn't any way of explicitly referencing variables that are in the same method but in different code blocks.


The point is that you can already refer to the local variable s within the lambda expression - so introducing another variable called s would be pretty confusing. The C# compiler is helping you to avoid writing unreadable code.

The specification could have allowed the "extra-local" variable to just hide the local variable, certainly - but I don't think that would have been a good idea.


The declaration string s = "hello"; is declared outside the lambda expression and, therefore, accessible from within it. As a result the declaration of s => s.StartsWith("a") conflicts with the declaration of s outside the lambda expression, i.e. the compiler cannot figure out to which s you are referring in the statement s.StartsWith("a").

To show the problem consider the following code:

static void Main(string[] args)
{
    string s = "hello"; // Line 1
    var test = new[] { "abd", "def" }.Select(x => x.StartsWith("a") && s.StartsWith("h")); // Line 2
}

This will only return true in the selection if ths string in the array (represented by x within the lambda) starts with "a" and the string s starts with an "h".

BTW, your statement will only return a ICollection<bool> and not ICollection<string> as you might expect ... to return the strings starting with "a" use:

new[] { "abd", "def" }.Where(x => x.StartsWith("a"));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜