为什么(以及如何)Enum的顺序会影响ToString值?

时间:2011-01-04 10:20:57

标签: c# .net c#-4.0 enums

嘿伙计们,我一直有关于枚举值的“顺序”的问题。这有点难以解释,这就是我编写代码的原因:

class Program
{
    public enum EnumA
    {
        One = 1,
        Two = One,
        Three = Two,
        Four = 4
    }

    public enum EnumB
    {
        One = 1,
        Two = One,
        Four = 4,
        Three = Two
    }

    public enum EnumC
    {
        Two = One,
        Three = Two,
        Four = 4,
        One = 1
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Enum A:");
        Console.WriteLine(EnumA.One);
        Console.WriteLine(EnumA.Two);
        Console.WriteLine(EnumA.Three);
        Console.WriteLine(EnumA.Four);
        Console.WriteLine();

        Console.WriteLine("Enum B:");
        Console.WriteLine(EnumB.One);
        Console.WriteLine(EnumB.Two);
        Console.WriteLine(EnumB.Three);
        Console.WriteLine(EnumB.Four);
        Console.WriteLine();

        Console.WriteLine("Enum C:");
        Console.WriteLine(EnumC.One);
        Console.WriteLine(EnumC.Two);
        Console.WriteLine(EnumC.Three);
        Console.WriteLine(EnumC.Four);
        Console.WriteLine();

        Console.ReadLine();
    }
}

输出结果为:

Enum A: 二 二 二 四

Enum B: 三 三 三 四

枚举C: 一 一 一 四

我的问题是:为什么!?我找不到输出的逻辑。大部分时间都有一些逻辑可以找到,所以我希望你们能够对这个问题有所了解。

我使用VS2010 / .Net 4.0来编译和运行代码。

2 个答案:

答案 0 :(得分:12)

行为被指定为“未定义”(我以为我刚刚发现了一种模式,但显然没有。)documentation明确地将其调出:

  

如果多个枚举成员具有相同的基础值,并且您尝试根据其基础值检索枚举成员名称的字符串表示形式,则您的代码不应对该方法将返回的名称做出任何假设。

使您的枚举值不同,或者明确地创建从值到所需名称的地图。

答案 1 :(得分:5)

首先要注意的是,如果你对IL进行反编译,那么对WriteLine的调用看起来非常相似:

    L_000c: ldc.i4.1 
    L_000d: box ConsoleApplication2.Program/EnumA
    L_0012: call void [mscorlib]System.Console::WriteLine(object)
    L_0017: nop 
    L_0018: ldc.i4.1 
    L_0019: box ConsoleApplication2.Program/EnumA
    L_001e: call void [mscorlib]System.Console::WriteLine(object)
    L_0023: nop 
    L_0024: ldc.i4.1 
    L_0025: box ConsoleApplication2.Program/EnumA
    L_002a: call void [mscorlib]System.Console::WriteLine(object)
    L_002f: nop 
    L_0030: ldc.i4.4 
    L_0031: box ConsoleApplication2.Program/EnumA
    L_0036: call void [mscorlib]System.Console::WriteLine(object)
    L_003b: nop 
    L_003c: call void [mscorlib]System.Console::WriteLine()
    L_0041: nop 

也就是说,加载这些枚举值会将值“1”加载三次,然后调用WriteLine。所以我们不应该惊讶于前3个调用都会产生相同的值。

我尝试了一些实验,但不能指出您可以依赖的任何特定(无证件)行为来预测将打印哪个值。