C#6中最便捷的新功能之一是nameof
,它允许程序员有效地消除magic strings的使用。
根据文档,nameof
返回一个字符串:
用于获取变量,类型或成员的简单(非限定)字符串名称。
在以下代码示例中使用显式输入可以正常工作:
string magicString = nameof(magicString);
但是,在使用var
keyword:
var magicString = nameof(magicString);
编译器抛出错误:
无法使用局部变量' magicString'在宣布之前
然后,我对Visual Studio中提供的C#Interactive窗口进行了一些实验。同样,第一个例子运行正常,但第二个例子这次抛出了一个不同的错误:
错误CS7019:' magicString'的类型由于其初始化程序直接或间接引用了定义,因此无法推断。
nameof
表达式清楚地返回一个字符串,那么为什么编译器在与初始化变量一起使用时会隐式输入它?
答案 0 :(得分:23)
语言团队认为这不符合规范的复杂性。
您可以看到讨论here。
这种行为的根本原因是规范说(§8.5.1)用var
声明的名称在声明语句中不可见,因为在nameof
之前,没有办法进入这可能是有效的。
隐式类型的局部变量声明受以下限制:
- ...
- 初始化表达式不能引用声明的变量本身
如果没有var
,int x = x = 1;
或int x = 1, y = x;
等语句是合法的;使用var
时,该格式中的任何内容均无效。
答案 1 :(得分:13)
声明变量并在同一语句中赋值的能力是语法糖。例如,当你这样说:
string magicString = nameof(magicString);
你真正说的是:
string magicString;
magicString = nameof(magicString);
由于已声明magicString
,因此您可以在下一个逻辑语句中将其用作naemof
运算符的一部分。这是因为magicString
现在是后续语句可见的范围的一部分。
现在,当您使用var
时,上述情况并不成立,因为使用var
进行赋值的任何内容实际上只是一个语句的一部分,而不是两个语句的语法糖。上面的例子。变量magicString
实际上不会在之后你的函数调用/运算符/赋值声明,因此变量不是范围的一部分,直到它具有完成了作业,即在下一个声明中。
SLaks提到了the original discussion about this issue,但the notes from this later C# design team meeting中关于“var var x = nameof(x)是否有效”这一问题的指出:
这与任何其他构造相同,即:not。这是 不是nameof的特例,它似乎并不值得特别 套管允许它。
换句话说,它并非特定于nameof
。