使用 C# 6 nameof 的隐式和显式类型

Implicit and explicit typing with C# 6 nameof

C# 6 中最方便的新功能之一是 nameof, which allows the programmer to effectively eliminate the use of magic strings

根据文档,nameof returns 一个字符串:

Used to obtain the simple (unqualified) string name of a variable, type, or member.

在以下代码示例中使用显式键入就可以正常工作:

string magicString = nameof(magicString);

但是,在 var keyword 中使用隐式类型时:

var magicString = nameof(magicString);

编译器报错:

Cannot use local variable 'magicString' before it is declared

然后我对 Visual Studio 中提供的 C# Interactive window 进行了更多试验。同样,第一个示例运行良好,但这次第二个示例抛出不同的错误:

error CS7019: Type of 'magicString' cannot be inferred since its initializer directly or indirectly refers to the definition.

nameof表达式明明returns是一个字符串,为什么编译器不能在与初始化变量一起使用时隐式类型化它?

在同一语句中声明变量并对其赋值的能力是语法糖。例如,当您这样说时:

string magicString = nameof(magicString);

你真正想说的是:

string magicString;
magicString = nameof(magicString);

由于 magicString 已经声明,您可以在下一个逻辑语句中将其用作 naemof 运算符的一部分。这是因为 magicString 现在是对后续语句可见的 scope 的一部分。

现在,当您使用 var 时,以上内容不成立,因为任何使用 var 进行赋值的东西实际上都是一个语句的一部分,而不是两个语句的语法糖像上面的例子。变量 magicString 直到 函数调用/运算符/赋值之后才真正被声明,因此变量不是 scope[= 的一部分36=] 直到它完成赋值,即在下一个语句中。

SLaks 在 "Should var x = nameof(x) work?" 的问题上提到 the original discussion about this issue, but what is pointed out in the notes from this later C# design team meeting 关于这个问题:

This works the same as with any other construct, i.e.: not. This is not a special case for nameof, and it doesn't seem worth special casing to allow it.

换句话说,它不特定于 nameof

语言团队认为这不值得规范的复杂性。

可以看到讨论here.

此行为的根本原因是规范说 (§8.5.1) 用 var 声明的名称在声明语句中不可见,因为在 nameof 之前,没有这可能是有效的方式。

Implicitly typed local variable declarations are subject to the following restrictions:

  • ...
  • The initializer expression cannot refer to the declared variable itself

没有var,像int x = x = 1;int x = 1, y = x;这样的语句是合法的;对于 var,该形式的任何内容均无效。