问题 为什么我不能在属性中使用字符串插值?


我在C#6.0中编写单元测试(MSTest),我注意到编译器在属性中处理字符串插值的方式有些奇怪。

为什么这样做:

[TestCategory(nameof(MyClass) + "-UnitTest")]

什么时候不这样?

[TestCategory($"{nameof(MyClass)}-UnitTest")]

忽略这可能不是分类测试的好方法;我很好奇为什么编译器允许一个而不是另一个。


2579
2017-08-05 22:36


起源

是否 string.Format("{0}-UnitTest", nameof(MyClass)) 工作? - Blorgbeard


答案:


当编译器遇到插值字符串时,它立即将其转换为调用 String.Format 所以...

[TestCategory($"{nameof(MyClass)}-UnitTest")]

成为...

[TestCategory(string.Format("{0}-UnitTest", nameof(MyClass)))]

属性要求它们的参数是常量表达式 但上述表达式在执行时间之前不会被评估,因此错误...

CS0182 属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式...

 知道所有的信息  在编译时可用,但编译器不够聪明,无法弄明白。

nameof 与插值字符串的工作方式略有不同,因为它是 在编译时评估 所以没有错误。


7
2017-08-06 08:32





插值字符串不是常量值。该值在运行时确定,即使在您的情况下,所有输入都可以在编译时计算。


6
2017-08-05 22:41





属性参数必须是编译时常量。而 nameof() 是一个常数(见 nameof()是在编译时评估的吗?),字符串插值功能本身不是。

插值字符串表达式通过将包含的表达式替换为表达式结果的ToString表示来创建字符串。


3
2017-08-05 22:42





字符串插值发生在 运行 和属性存在于 编译时间。 所以你的编译器无法解决这个问题,因为它会像这样编译:

[TestCategory(new FormattableString
  {
    Format = "{0}-UnitTest",
    Args = new object[] { nameof(MyClass)}
  })]

0
2017-08-05 22:42