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

发布于 2024-10-10 09:37:10 字数 1335 浏览 0 评论 0原文

我对枚举值的“顺序”有疑问。这有点难以解释,这就是为什么我写了一些代码:

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: 二 二 二 四个

枚举 B: 三 三 三 四个

枚举 C: 一 一 一 四

我的问题是:为什么!?我找不到输出的逻辑。大多数时候都是有逻辑可寻的,所以我希望你们能对这个问题有所启发。

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

I have problems with the "order" of the values of an enum. It's a little difficult to explain, that's why I wrote up some code:

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();
    }
}

The output is:

Enum A:
Two
Two
Two
Four

Enum B:
Three
Three
Three
Four

Enum C:
One
One
One
Four

My question is: WHY!? I can't find the logic to the output. Most of the time there is some logic to be found, so I hope you guys can shine some light on this issue.

I used VS2010 / .Net 4.0 to compile and run the code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听你说爱我 2024-10-17 09:37:10

该行为被指定为“未定义”(我以为我刚才发现了一个模式,但显然没有。) aspx">文档明确指出了这一点:

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

要么使您的枚举值不同,要么显式创建从值到所需名称的映射。

The behaviour is specified to be "undefined" (I thought I'd spotted a pattern just now, but apparently not.) The documentation explicitly calls this out:

If multiple enumeration members have the same underlying value and you attempt to retrieve the string representation of an enumeration member's name based on its underlying value, your code should not make any assumptions about which name the method will return.

Either make your enum values distinct, or explicitly create a map from value to desired name.

筑梦 2024-10-17 09:37:10

如果反编译 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 个调用都产生相同值感到惊讶。

我已经尝试了一些实验,但无法指出您可以依赖的任何特定(未记录)行为来预测将打印哪个值。

The first thing to observe, if you decompile the IL, is that the calls to WriteLine all look remarkably similar:

    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 

That is, the loading of these enum values is loading the value "1" three times, and then calling WriteLine. So we should not be surprised that the 1st 3 calls all result in the same value.

I've tried a few experiments, but can't point to any particular (undocumented) behaviour you can rely on to predict which value will be printed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文