【问题标题】:Enum.GetName() As Constant propertyEnum.GetName() 作为常量属性
【发布时间】:2016-06-16 20:39:49
【问题描述】:

我已经在 C# 中工作了大约 8 个月,如果这是愚蠢的,请原谅我......

我有一个枚举,我需要在一个类中多次使用字符串值。所以我想使用 Enum.GetName() 将它设置为一个没有问题的字符串变量。我就是这么干的……

private string MyEnumString = Enum.GetName(typeof(MyEnum), MyEnum.Name);

而且效果很好。

但是我试图更好地保护它,因为这个特定的 Enum 比所有其他 Enum 都更重要,如果我不小心以某种方式更改了字符串值,那将不是一件好事,所以我尝试将其设为 const 像这样。

private const string MyEnumString = Enum.GetName(typeof(MyEnum), MyEnum.Name);

在我看来这似乎很好,因为它应该在编译时就知道了。

但 Visual Studio 2013 会引发错误,提示“无法解析符号 GetName”。我知道当它没有被标记为“const”时它可以工作。

所以这让我有两个问题? 为什么它松散引用 GetName 枚举? (经过一番研究,我怀疑这与 GetName 是一种方法有关,而不是 Enum 类的属性,但错误消息对我来说没有意义)

最后有没有办法将 MyEnum.Name 的名称读取为 const 字符串,而不是我正在做的事情?

【问题讨论】:

  • 您可以改用 Visual Studio 2015 吗?然后你可以使用nameof...
  • “在我看来这似乎很好,因为它应该在编译时就知道了。” - 仅当编译器知道Enum.GetName 做什么,它不知道...(就像它不知道Math.Sqrt 做什么一样,所以const double x = Math.Sqrt(2.0); 也不会编译。)
  • @JonSkeet 不幸的是,我们暂时必须坚持使用 Visual Studio 2013,但我将不得不研究“nameof”,因为我们将在年底前进入 2015 年。

标签: c# enums compiler-errors constants


【解决方案1】:

将其设为只读:

private readonly string MyEnumString = Enum.GetName(typeof(MyEnum), MyEnum.Name);

那以后就不能改了。

您不能将调用方法的结果分配给常量; C# 只是不允许它 - 编译器必须在编译时调用该方法,甚至可能在它被编译之前(不仅它必须生成 IL,它还必须使用 JIT 编译器来编译它伊尔)。

Enum.GetName(typeof(MyEnum), MyEnum.Name); 正在调用一个方法,因此您不能将结果分配给常量。

[编辑] 正如 Jon Skeet 在上面的评论中所说,如果使用 C#6 或更高版本(即 VS2015 或更高版本),您可以使用 nameof

private const string MyEnumString = nameof(MyEnum.Name);

nameof 之所以有效,是因为在这里您不是调用任意方法,而是使用编译器功能来访问类型的名称。

【讨论】:

    【解决方案2】:

    您不能将方法的结果用作常量,因为方法评估只能在运行时进行。常量的值必须在编译时已知。为了让编译器能够评估该常量,它需要知道 Enum.GetName 的语义并在编译时执行它,这是不可能的

    您可以将其标记为static readonly。这样,每个声明它的类型都会设置一次,并且在运行时不能再更改。

    【讨论】:

      【解决方案3】:

      它甚至可能在运行时都不知道

      来自MSDN

      如果多个枚举成员具有相同的基础值,GetName 方法保证它将返回这些枚举成员之一的名称。但是,它不保证总是返回同一个枚举成员的名称

      (强调)

      void Main()
      {
          Console.WriteLine (Enum.GetName(typeof(Test),Test.One));
      }
      
      public enum Test
      {
         Zero,
         One,
         Two,
         Uno = 1,
         Dos = 2,
      }
      

      我一直得到上​​述程序的输出Uno

      不知道的原因是枚举被编译为底层的。上面的调用本质上编译为Enum.GetName(typeof(Test), 1)GetName 查找具有该值的成员以查找名称。它是如何做到的,显然是一个实现细节,可能无法产生一致的结果。

      可以在 C#6 及更高版本中使用nameof

      private const string MyEnumString = nameof(MyEnum.Name);
      

      【讨论】:

        猜你喜欢
        • 2016-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-14
        • 2016-10-20
        • 2016-08-20
        • 1970-01-01
        • 2012-09-09
        相关资源
        最近更新 更多