Почему (и как) порядок перечисления влияет на значение ToString? - PullRequest
8 голосов
/ 04 января 2011

Эй, ребята, у меня были проблемы с "порядком" значений перечисления. Это немного сложно объяснить, поэтому я написал код:

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: Три Три Три Четыре

Enum C: Один Один Один Четыре

Мой вопрос: ПОЧЕМУ? Я не могу найти логику для вывода. Большую часть времени можно найти какую-то логику, поэтому я надеюсь, что вы, ребята, сможете пролить свет на эту проблему.

Я использовал VS2010 / .Net 4.0 для компиляции и запуска кода.

Ответы [ 2 ]

12 голосов
/ 04 января 2011

Поведение определено как «неопределенное» (я думал, что только сейчас заметил образец, но, очевидно, нет.) Документация явно вызывает это:

Если несколько членов перечисления имеют одинаковое базовое значение, и вы пытаетесь получить строковое представление имени члена перечисления на основе его базового значения, ваш код не должен делать никаких предположений относительно имени, которое будет возвращать метод.

Либо сделайте ваши значения перечисления различными, либо явно создайте карту от значения до желаемого имени.

5 голосов
/ 04 января 2011

Первое, что нужно заметить, если вы декомпилируете 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 вызова все приводят к одинаковому значению .

Я пробовал несколько экспериментов, но не могу указать на какое-либо конкретное (недокументированное) поведениеВы можете рассчитывать, какое значение будет напечатано.

...