lambda中的alpha转换

mat*_*thk 1 c# lambda programming-languages lexical-scope

为什么C#不支持alpha转换?

int n = 3;
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);
Console.Out.WriteLine("N value = " + n);
Run Code Online (Sandbox Code Playgroud)

产量:

名为'n'的局部变量不能在此范围内声明,因为它会给'n'赋予不同的含义,'n'已在'父或当前'范围内用于表示其他内容

有没有我不知道的颗粒原因,因为它听起来很傻?

Eri*_*ert 11

首先,你对奇怪的测试是错误的.

你的问题的答案是否定你的问题的前提.这与alpha转换没有任何关系.

它也与"词汇范围"没有任何关系,其中leppie似乎意味着与我对词汇范围的理解不同的东西.C#是一种词法范围的语言.

现在,我想强调,在C#中声明两个本地人是非法的,其中一个隐藏另一个.隐藏在其他范围内是完全合法的; 类型参数可以隐藏外部类型参数(虽然这样做真的非常愚蠢;不要这样做.)字段可能隐藏基类字段(尽管你应该将隐藏字段标记为'新',以强调这一事实.)本地人可能隐藏一种方法.等等.

但是本地人可能不会隐藏另一个本地,因为(1)这样做会导致bug场,并且(2)它违反了关于使用简单名称的更一般规则.

关于名称的规则是这里有趣的规则.如果你这样做,你会得到类似的错误:

class C
{
    int n;
    void M()
    {
        Console.WriteLine(n); // n means this.n
        Func<double, double> f = n=>n; // n means the formal parameter
    }
}
Run Code Online (Sandbox Code Playgroud)

您得到的错误是因为您违反了C#规则,简单名称必须在首次使用它的本地范围内具有一致的含义.

程序中"n"表示一行中的一件事,而下一行则完全不同,这些程序容易混淆和容易出错,因此是非法的.

如果你想这样做那么'n'的两个含义必须是非重叠的范围:

class C
{
    int n;
    void M()
    {
        {
          Console.WriteLine(n); // n means this.n
        }
        Func<double, double> f = n=>n; // n means the formal parameter
    }
}
Run Code Online (Sandbox Code Playgroud)

这是合法的,因为现在n的两个用法是在非重叠的范围内.

这个问题与alpha转换没有任何关系.C#在需要时进行alpha转换就好了.

这是因为 C#具有词法范围,编译器可以确定您违反了此规则.这并不是C#缺乏词汇范围的证据; 它证明它具有词汇范围.

有关此规则的更多信息,请参阅我关于此主题的文章:

http://blogs.msdn.com/b/ericlippert/archive/2009/11/02/simple-names-are-not-so-simple.aspx