27

C# 6 中最方便的新特性之一是nameof,它允许程序员有效地消除魔术字符串的使用。

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

用于获取变量、类型或成员的简单(非限定)字符串名称。

这适用于以下代码示例中的显式键入:

string magicString = nameof(magicString);

var但是,当使用带有关键字的隐式类型时:

var magicString = nameof(magicString);

编译器抛出错误:

在声明之前不能使用局部变量“magicString”

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

错误 CS7019:无法推断“magicString”的类型,因为它的初始化程序直接或间接引用了定义。

表达式明明返回的nameof是一个字符串,那么为什么编译器在与初始化变量一起使用时不能隐式输入呢?

4

2 回答 2

23

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

你可以在这里看到讨论。

这种行为的根本原因是规范说(第 8.5.1 节)声明的名称var在声明语句中不可见,因为在之前nameof,没有任何方法可以有效。

隐式类型的局部变量声明受到以下限制:

  • ...
  • 初始化表达式不能引用声明的变量本身

没有, 类似或的var陈述是合法的;,该形式的任何内容均无效。int x = x = 1;int x = 1, y = x;var

于 2016-03-30T14:31:15.833 回答
13

声明变量并在同一语句中分配它的能力是语法糖。例如,当你这样说时:

string magicString = nameof(magicString);

你真正想说的是:

string magicString;
magicString = nameof(magicString);

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

现在,当您使用时,上述内容并不成立,var因为var用于进行赋值的任何内容实际上都是一个语句的一部分,而不是像上面示例中的两个语句的语法糖。直到您的函数调用/运算符/赋值之后,该变量magicString才真正被声明,因此该变量在完成赋值之前不是作用域的一部分 ,即在下一个语句中。

SLaks 提到了关于这个问题的原始讨论,但是在后来的 C# 设计团队会议关于这个问题的“Should var x = nameof(x) work?”问题上的注释中指出了什么:

这与任何其他构造相同,即:不是。这不是 nameof 的特例,而且似乎不值得特殊的大小写来允许它。

换句话说,它不是特定于nameof.

于 2016-03-30T14:06:48.013 回答