Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are negative enum members enumerated last by foreach?

Tags:

c#

enums

In C#, if we define an enum that contains a member correspondingto a negative value, and then we iterate over that enum's values, the negative value does not come first, but last. Why does that happen? In other languages (C, C++, Ada, etc), iterating over an enum will give you the order in which you defined it.

MSDN has a good example of this behavior:

using System;

enum SignMagnitude { Negative = -1, Zero = 0, Positive = 1 };

public class Example
{
    public static void Main()
    {
        foreach (var value in Enum.GetValues(typeof(SignMagnitude)))
        {
            Console.WriteLine("{0,3}     0x{0:X8}     {1}",
                              (int) value, ((SignMagnitude) value));
        }   
    }
}

// The example displays the following output: 
//         0     0x00000000     Zero 
//         1     0x00000001     Positive 
//        -1     0xFFFFFFFF     Negative
like image 224
gmletzkojr Avatar asked Aug 09 '13 14:08

gmletzkojr


People also ask

Can enum have negative values?

Each entity is called an Enum. An Enum has a Label string. An Enum has a Value. (The Value can be positive or negative Integer.)

Do enums have to be sequential?

There is nothing that requires them to be sequential. Your enum definition is fine and will compile without issue.

Can multiple enums have the same value?

Two enum names can have same value. For example, in the following C program both 'Failed' and 'Freezed' have same value 0.

Can enum have float values?

Enums can only be ints, not floats in C# and presumably unityScript.


1 Answers

From the very documentation page you link to, my emphasis:

The elements of the array are sorted by the binary values of the enumeration constants (that is, by their unsigned magnitude).

Digging into the CLR code (the 2.0 SSCLI) and getting far lower-level than I'm really comfortable with, it looks like ultimately this is because internally enum values are stored in something that looks like this (note this is C++):

class EnumEEClass : public EEClass
{
    friend class EEClass;

 private:

    DWORD           m_countPlusOne; // biased by 1 so zero can be used as uninit flag
    union
    {
        void        *m_values;
        BYTE        *m_byteValues;
        USHORT      *m_shortValues;
        UINT        *m_intValues;
        UINT64      *m_longValues;
    };
    LPCUTF8         *m_names;

As can be seen, it's unsigned types that hold the actual values - so when these values are emitted for enumeration, naturally they are in their unsigned order.

like image 132
2 revs Avatar answered Dec 16 '22 10:12

2 revs