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

时间:2015-08-05 22:36:07

标签: c# c#-6.0

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

为什么这样做:

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

什么时候不这样?

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

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

4 个答案:

答案 0 :(得分:8)

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

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

...变为

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

Attributes require that their arguments be constant expressions但是上述表达式在执行时才会被评估,因此错误......

  

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

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

nameof与插值字符串的工作方式略有不同,因为它是evaluated at compile-time所以没有错误。

答案 1 :(得分:6)

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

答案 2 :(得分:3)

属性参数必须是编译时常量。虽然nameof()是常量(请参阅Is nameof() evaluated at compile-time?),但字符串插值功能本身不是。

  

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

答案 3 :(得分:0)

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

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