【问题标题】:Implicit and explicit typing with C# 6 nameof使用 C# 6 nameof 进行隐式和显式类型
【发布时间】:2016-03-30 14:00:26
【问题描述】:

C# 6 中最方便的新功能之一是nameof,它允许程序员有效地消除对magic strings 的使用。

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

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

在以下代码示例中显式输入效果很好:

string magicString = nameof(magicString);

但是,当使用 var keyword 的隐式类型时:

var magicString = nameof(magicString);

编译器抛出错误:

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

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

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

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

【问题讨论】:

  • 老实说,从语义上讲,string magicString = nameof(magicString) 有效的事实比 var magicString = nameof(magicString) 无效的事实更让我困扰
  • 因为编译器会先用default(T)初始化变量,然后赋值nameof()的结果。
  • 语言团队认为这不值得规范复杂性。 github.com/dotnet/roslyn/issues/766
  • @AlfieGoodacre:var 不是这样工作的。
  • @SLaks:您应该将其发布为答案,因为它是一个。另请参阅链接问题 (#7031)。

标签: c# c#-6.0 nameof


【解决方案1】:

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

你可以看到讨论here

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

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

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

没有var,像int x = x = 1;int x = 1, y = x;这样的声明是合法的;使用var,该形式的任何内容均无效。

【讨论】:

  • int x = y, y = x; 实际上是不合法的,因为y 在声明之前就已使用。 int x = 1, y = x; 是合法的,但是(但不是很了不起)。 var x = 1, y = x; 又是非法的——不是因为任何引用,而是因为 var 不允许使用多个声明符,这是一个单独的问题。
  • @JeroenMostert:是的;我的意思是x = 1。而且,是的。
  • @JeroenMostert:确实,这是一个单独但相关的问题。当我们最初设计 var 时,问题出现了,var x = SomeInt(), y = SomeDouble(); 应该是什么意思?我们应该说vardouble 替换,如果用户实际进行了替换,这将是合法的,还是说x 是int 而y 是double?对用户的民意调查显示,它被分成了 50-50,因此我们只是将其定为非法。 50% 的用户认为您理解错误的功能可能是一个糟糕的功能。
【解决方案2】:

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

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 x = nameof(x) 工作吗?”的问题指出了这个问题:

这与任何其他构造相同,即:不是。这是 不是nameof的特例,而且似乎不值得特别 套管允许它。

换句话说,它并不特定于nameof

【讨论】:

  • 不幸的是,我无法访问 C# 6 (nameof),但如果有人可以帮助我用一些 IL 代码证明这一点,我将不胜感激。
  • 证明这一点的方法是参考语言规范,而不是 IL 代码。 IL 只演示了(一个特定的)编译器发生了什么,我们已经知道它在这种特殊情况下会发生什么(它拒绝代码)。它在“类似”情况下的作用无关紧要。
  • 编译器不是简单地将nameof(magicString) 替换为"magicString" 吗? Try Roslyn。不确定这在这种情况下是否相关
  • @JeroenMostert -- 实际上,我真正想证明的是nameof正确 代码中的工作方式,即IL 是由正确使用@987654336 的语句产生的@,例如var x = "hello"; var y = nameof(x)。这将有助于阐明“奇怪”的行为。
  • nameof 不是一个调用,而是一个运算符,任何nameof 表达式的类型都是已知的(string),无论其操作数如何。编译器当然可以接受var magicString = nameof(magicString),实现者只是决定不适应这种情况。
猜你喜欢
  • 2011-07-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 2010-11-13
  • 1970-01-01
  • 2017-01-30
  • 2013-09-02
  • 1970-01-01
相关资源
最近更新 更多