我在C#6.0中编写单元测试(MSTest),我注意到编译器在属性中处理字符串插值的方式有些奇怪。
为什么这样做:
[TestCategory(nameof(MyClass) + "-UnitTest")]
什么时候不这样?
[TestCategory($"{nameof(MyClass)}-UnitTest")]
忽略这可能不是分类测试的好方法;我很好奇为什么编译器允许一个而不是另一个。
我在C#6.0中编写单元测试(MSTest),我注意到编译器在属性中处理字符串插值的方式有些奇怪。
为什么这样做:
[TestCategory(nameof(MyClass) + "-UnitTest")]
什么时候不这样?
[TestCategory($"{nameof(MyClass)}-UnitTest")]
忽略这可能不是分类测试的好方法;我很好奇为什么编译器允许一个而不是另一个。
当编译器遇到插值字符串时,它立即将其转换为调用 String.Format
所以...
[TestCategory($"{nameof(MyClass)}-UnitTest")]
成为...
[TestCategory(string.Format("{0}-UnitTest", nameof(MyClass)))]
属性要求它们的参数是常量表达式 但上述表达式在执行时间之前不会被评估,因此错误...
CS0182 属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式...
您 知道所有的信息 是 在编译时可用,但编译器不够聪明,无法弄明白。
nameof
与插值字符串的工作方式略有不同,因为它是 在编译时评估 所以没有错误。
插值字符串不是常量值。该值在运行时确定,即使在您的情况下,所有输入都可以在编译时计算。
属性参数必须是编译时常量。而 nameof()
是一个常数(见 nameof()是在编译时评估的吗?),字符串插值功能本身不是。
插值字符串表达式通过将包含的表达式替换为表达式结果的ToString表示来创建字符串。
字符串插值发生在 运行 和属性存在于 编译时间。 所以你的编译器无法解决这个问题,因为它会像这样编译:
[TestCategory(new FormattableString
{
Format = "{0}-UnitTest",
Args = new object[] { nameof(MyClass)}
})]