【问题标题】:Why can't I use string interpolation in an attribute?为什么我不能在属性中使用字符串插值?
【发布时间】:2015-10-28 21:43:34
【问题描述】:

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

为什么会这样:

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

什么时候没有?

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

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

【问题讨论】:

标签: c# c#-6.0


【解决方案1】:

当编译器遇到内插字符串时,它会立即将其转换为对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,所以没有错误。

【讨论】:

  • 有什么解决方法可以在 Attribute 中使用 nameof 吗?
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-30
        • 1970-01-01
        • 1970-01-01
        • 2012-06-11
        相关资源
        最近更新 更多