我在C#6.0中编写单元测试(MSTest),我注意到编译器在属性中处理字符串插值的方式有些奇怪。
为什么这样做:
[TestCategory(nameof(MyClass) + "-UnitTest")]
什么时候不这样?
[TestCategory($"{nameof(MyClass)}-UnitTest")]
忽略这可能不是对我的测试进行分类的好方法;我很好奇为什么编译器允许一个而不是另一个。
答案 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)}
})]