C#LINQ / Lambda范围问题

时间:2010-06-28 11:22:42

标签: c# linq lambda

我收到错误:

  

名为's'的局部变量不能   在此范围内声明,因为它   会对's'赋予不同的含义,   已经在“孩子”中使用   范围表示别的东西。

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

为什么?

我猜想第1行的's'会被'.Select(s => ..'第2行的'decleration)阴影但是 - 据我所知 - 事实并非如此。

PS我不确定是否用正确的术语标出 - 如果有更好的词/短语,请纠正我。

3 个答案:

答案 0 :(得分:6)

出现错误的原因与普通代码块(如 if 语句或循环)相同,您无法声明与代码块外部名称相同的变量。

这与类变量和方法变量不同,您可以使用 this 关键字显式引用类变量。

我认为 this 关键字是关键,因为没有任何方法可以显式引用同一方法但在不同代码块中的变量。

答案 1 :(得分:3)

关键是你已经可以在lambda表达式中引用局部变量s了 - 所以引入另一个名为s的变量会非常混乱。 C#编译器正在帮助您避免编写不可读的代码。

规范可以允许“extra-local”变量只是隐藏本地变量,但我认为这不是一个好主意。

答案 2 :(得分:1)

声明string s = "hello";在lambda表达式之外声明,因此可以在其中访问。因此,s => s.StartsWith("a")的声明与lambda表达式之外的s声明冲突,即编译器无法确定您在语句s中引用的s.StartsWith("a")

要显示问题,请考虑以下代码:

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
}

如果数组中的字符串(由lambda中的true表示)以“a”开头且字符串x以“a”开头,则只会在选择中返回s H”。

顺便说一下,你的陈述只会返回一个ICollection<bool>而不是ICollection<string>,如你所料......返回以“a”开头的字符串:

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