这难道不是错误的吗?
不,这个并没有错。这是C#规范7.5.2.1章节“块中简单名称的不变含义”正确的实现。
该规范声明:
对于在表达式或声明符中作为简单名称出现的给定标识符的每个出现, 在该出现的局部变量声明空间内,同一标识符作为简单名称的每个其他出现都必须引用相同的实体。 这个规则确保了一个名称在一个给定的块、switch块、 for-, foreach- or using-statement, 或匿名函数内始终具有相同的意义。
为什么C#无法区分两个范围?
这个问题是无意义的;显然编译器能够区分两个范围。 如果编译器不能区分两个范围,那么怎么会产生错误呢?错误消息说明存在两个不同的范围,因此已经区分了这两个范围。
第一个IF的范围为什么不应该完全与方法的其余部分分开?
不,不应该这样做。条件语句结果中块语句定义的范围(和局部变量声明空间)在词汇上是方法主体所定义的外层块的一部分。因此,适用于外层块内容的规则也适用于内层块的内容。
我无法从if之外调用var,因此错误消息是错误的,因为第一个var和第二个范围无关。
这是完全错误的。仅仅因为局部变量不再在范围内,就得出外层块不包含错误的结论是不成立的。错误消息是正确的。
这里的错误与任何变量的范围是否重叠无关;唯一相关的是在一个块中使用相同的简单名称来引用两个完全不同的东西。C#要求一个简单名称在首次使用它的块中具有一个含义。例如:
class C
{
int x;
void M()
{
int x = 123;
}
}
那是完全合法的;外部x的范围与内部x的范围重叠,但这不是一个错误。错误的是:
class C
{
int x;
void M()
{
Console.WriteLine(x);
if (whatever)
{
int x = 123;
}
}
}
因为现在"X"这个简单名称在M的函数体内有两种不同的含义——它既表示"this.x",又表示本地变量"x"。在同一个块中使用相同的简单名称表示两个完全不同的事情,这会让开发人员和代码维护者感到困惑,所以这是非法的。
我们允许并行块包含以两种不同方式使用的相同简单名称;这是合法的:
class C
{
int x;
void M()
{
if (whatever)
{
Console.WriteLine(x);
}
if (somethingelse)
{
int x = 123;
}
}
}
因为现在唯一包含两个不一致使用 x 的块是外层块,但是该块没有 直接 包含任何 "x" 的用法,只有间接地使用。
var
是C# 3.0中的关键字。 - John Saunders