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

m-y*_*m-y 6 c# enums

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

Pol*_*ity 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
}
Run Code Online (Sandbox Code Playgroud)

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

static readonly Encoding = Encoding.GetEncoding("GB2132");
Run Code Online (Sandbox Code Playgroud)

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

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

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

enum MyEnum
{   
    First,
    Second,
    Third
}

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

    if (test == MyEnum.Second)
    {
      // whatever
    }
}
Run Code Online (Sandbox Code Playgroud)

将由编译器解决:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

static void Main()
{
    int test = 0;

    if (test == 1 )
    {
      // whatever
    }
}
Run Code Online (Sandbox Code Playgroud)


key*_*rdP 7

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

[Enums]的加载方式与加载const值的方式相同.它们直接嵌入IL中.另一方面,字段需要字段加载指令(ldsfld),这将在某种程度上影响性能.因此,在典型用法中,枚举与const一样快; 字段有点慢.

(来源)