Novak
Novak

Reputation: 2768

C# Enum ignores names' order

I have the next object:

private enum Operation
{
        Power = 0x5E,             // ^
        Division = 0x2F,          // /
        Multiplication = 0x2A,    // *
        Subtraction = 0x2D,      // -
        Addition = 0x2B           // +
}

When I want to convert it into a char[] in the next way:

private static char[] GetOperators()
{
        List<char> ExistingOperators = new List<char>();

        foreach (Operation enumOperator in Enum.GetValues(typeof(Operation)))
        {
                ExistingOperators.Add((char)enumOperator);
                Console.WriteLine(enumOperator);
        }

        return ExistingOperators.ToArray<char>();
}

It writes on the console the values of the enums, but in sorted from small to big. The above example outputs:

Multiplication
Addition
Subtraction
Divison
Power

What I want to achieve: (so the array is in the same order as the enum declaration)

char[] { '^', '/', '*', '*', '-', '*' };

Thanks in advance.

Upvotes: 1

Views: 1114

Answers (2)

sisve
sisve

Reputation: 19781

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

Source: http://msdn.microsoft.com/en-us/library/system.enum.getvalues.aspx

Upvotes: 5

Paul Fleming
Paul Fleming

Reputation: 24526

You could use something along these lines to maintain order and associate a value. Note that the code is freehand (untested).

public ValueAttribute : Attribute
{
    public char Value { get; set; }
    public ValueAttribute(char value) { Value = value; }
}

private enum Operation
{
    [Value(0x5E)]
    Power = 1,
    [Value(0x2F)]
    Division = 2,
    [Value(0x2A)]
    Multiplication = 3,
    [Value(0x2D)]
    Subtraction = 4,
    [Value(0x2B)]
    Addition = 5,
}

private static char[] GetOperators()
{
    List<char> ExistingOperators = new List<char>();

    foreach (Operation enumOperator in Enum.GetValues(typeof(Operation)))
    {
            ExistingOperators.Add(enumOperator.Value());
            Console.WriteLine(enumOperator);
    }

    return ExistingOperators.ToArray<char>();
}

public static class Extensions
{
    public static char Value(this Operation op)
    {
        var attr = typeof(Operation)
            .GetField(op.ToString())
            .GetCustomAttributes(typeof(ValueAttribute), false)[0]
            as ValueAttribute;
        return attr.Value;
    }
}

Alternate using IndexAttribute:

public IndexAttribute : Attribute
{
    public int Index { get; set; }
    public IndexAttribute(int index) { Index = index; }
}

private enum Operation
{
    [Index(1)]
    Power = 0x5E,
    [Index(2)]
    Division = 0x2F,
    [Index(3)]
    Multiplication = 0x2A,
    [Index(4)]
    Subtraction = 0x2D,
    [Index(5)]
    Addition = 0x2B,
}

public struct Datum
{
    int Index { get; set; }
    char Value { get; set; }
    Operation Op { get; set; }
}
private static char[] GetOperators()
{
    IEnumerable<Datum> data = new List<Datum>();

    foreach (Operation enumOperator in Enum.GetValues(typeof(Operation)))
    {
        data.Add(new Datum 
        { 
            Index = enumOperator.Index(), 
            Value = (char)enumOperator,
            Op = enumOperator
        });
    }

    // assuming you can use LINQ
    data = data.OrderBy(d => d.Index);
    data.Foreach(d => Console.WriteLine(d => d.Op));

    return data.Select(d => d.Value).ToArray();
}

public static class Extensions
{
    public static char Index(this Operation op)
    {
        var attr = typeof(Operation)
            .GetField(op.ToString())
            .GetCustomAttributes(typeof(IndexAttribute), false)[0]
            as IndexAttribute;
        return attr.Index;
    }
}

Upvotes: 2

Related Questions