为什么Enums编译为常量而不是静态值?

时间:2011-12-30 04:29:01

标签: c# enums

我知道Enums被编译为常量,因此更改它们会导致重大变化。我想知道的是,为什么Enums的编译方式与静态只读变量相同?

3 个答案:

答案 0 :(得分:9)

两个给出的答案在技术上都是正确的,但是错过了使用静力学(readonly)对差异常数的解释。在C#中,常量总是比readonly快,原因很简单,最好用一个小代码示例表示:

const int MyConstant = 10;
static readonly int MyReadonly = 20;

static void Main()
{
    int result = MyConstant + MyReadonly;
    // the above statement will be resolved to:
    // int result = 10 + MyReadonly
}

在编译时,编译器将对常量的所有引用替换为该常量的实际值。它能够这样做,因为必须在编译时预定义常量。这与静态只读值不同,静态readonly值虽然是静态的,但实际上是在运行时解析的。请看以下示例:

static readonly Encoding = Encoding.GetEncoding("GB2132");

编译器无法知道GB2132是否实际存在于要运行此代码的计算机上。解决此值的唯一方法是在运行时。 Static确保值本身不绑定到实例的生命周期,并且readonly确保该值只能设置一次。编译器无法在编译时替换对该字段的引用,因为该值根本无法知道。

逻辑上,只有原始类型可以标记为常量。

现在,对于枚举,它非常简单。枚举只不过是带有标签的整数值。所以下面的代码:

enum MyEnum
{   
    First,
    Second,
    Third
}

static void Main()
{
    MyEnum test = MyEnum.First;

    if (test == MyEnum.Second)
    {
      // whatever
    }
}

将由编译器解决:

const int MyEnum_First = 0;
const int MyEnum_Second = 1;
const int MyEnum_Third = 2;

static void Main()
{
    int test = MyEnum_First;

    if (test == MyEnum_Second )
    {
      // whatever
    }
}

这反过来意味着对常量字段的实际引用可以用编译时已知的值替换,使得代码的最终版本类似于:

static void Main()
{
    int test = 0;

    if (test == 1 )
    {
      // whatever
    }
}

答案 1 :(得分:7)

它们可以比字段更有效,因此当它们可以直接嵌入到IL中时,不需要以相同的方式编译它们。

  

[枚举]加载相同   加载const值的方式。它们直接嵌入到   IL。另一方面,字段需要字段加载指令   (ldsfld)会对性能产生一定影响。因此,枚举   与典型用法中的const一样快;字段有点慢。

Source

答案 2 :(得分:1)

来自enum (C# Reference)

  

就像任何常量一样,所有对个体值的引用都是如此   枚举在编译时转换为数字文字

我错过了什么?