Raskolnikov
Raskolnikov

Reputation: 4009

How to get enum order?

If I have enum:

public enum ImportState : byte
{
     None = 0,
     ImportedWithChanges = 44,
     AwaitingApproval = 45,
     Removing = 66,
     Revalidating = 99,
};

How to get enum order? For example:

GetOrder(ImportState.None)

Should return 1(first in order)

GetOrder(ImportState.AwaitingApproval )

Should return 3 (third in order)

Upvotes: 1

Views: 5621

Answers (7)

SergeyVoskoboynikov
SergeyVoskoboynikov

Reputation: 51

What about this Solution?

var result = from r in Enum.GetValues<ImportState>()
         let expression =
         r == ImportState.Revalidating
            ? 0
            : r == ImportState.AwaitingApproval
                ? 1
                : r == ImportState.Removing
                    ? 2
                    : r == ImportState.ImportedWithChanges
                        ? 3
                        : 4
         orderby expression ascending
         select r.ToString();
Console.WriteLine(string.Join(", ", result));

Output: Revalidating, AwaitingApproval, Removing, ImportedWithChanges, None

Upvotes: 0

Sayse
Sayse

Reputation: 43330

Instead of using the order, you would be better to make better use of the flags. Consider the following

public enum ImportState : byte
{
     None = 0,
     ImportedWithChanges = 2,
     AwaitingApproval = 4,       
     Removing = 6,
     Revalidating = 8,
};
(double)state / Enum.GetValues(typeof(ImportState)).Cast<byte>().Max()

Example

Enums don't really have any sense of ordering, using the above probably still isn't perfect but it doesn't involve a made up order.

Upvotes: 0

xanatos
xanatos

Reputation: 111940

As other noticed, Enum.GetValues() returns the values of an enum sorted by value. Perhaps this isn't what you wanted... So, using a little reflection:

public class EnumOrder<TEnum> where TEnum : struct
{
    private static readonly TEnum[] Values;

    static EnumOrder()
    {
        var fields = typeof(Values).GetFields(BindingFlags.Static | BindingFlags.Public);
        Values = Array.ConvertAll(fields, x => (TEnum)x.GetValue(null));
    }

    public static int IndexOf(TEnum value)
    {
        return Array.IndexOf(Values, value);
    }
}

Example of use:

public enum Values
{
    Foo = 10,
    Bar = 1
}

int ix = EnumOrder<Values>.IndexOf(Values.Bar); // 1

Note that the C# specifications aren't clear if the "source code" ordering of an enum is maintained in the compiled program... At this time the C# compiler seems to maintain it, but there is no guarantee in the future...

The only two references I've found are:

Forward declarations are never needed in C# because, with very few exceptions, declaration order is insignificant

and

Declaration order for enum member declarations (§14.3) is significant when constant-expression values are omitted.

So as written, for the example I gave, the ordering is undefined and depends on the C# compiler!

Upvotes: 3

Tim Schmelter
Tim Schmelter

Reputation: 460340

You can use this LINQ query:

int position = Enum.GetValues(typeof(ImportState)).Cast<ImportState>()
    //.OrderBy(impState => (int)impState)
    .TakeWhile(impState => impState != ImportState.None)
    .Count() + 1;

It orders by the int-value of the enum-value, then it takes all until the searched value and counts them. I have omitted the OrderBy since Enum.GetValues automatically returns the order according to their int-value.

MSDN:

The elements of the array are sorted by the binary values of the enumeration constants

Upvotes: 0

Micke
Micke

Reputation: 2309

Enumerating the enum values, casting to an IEnumerable, converting to a List. This it is a simple matter of using IndexOf().

Note that for this to work, the enum must be declared in increasing order.

namespace ConsoleApplication1
{
    using System;
    using System.Linq;

    class Program
    {
        public enum ImportState : byte
        {
            None = 0,
            ImportedWithChanges = 44,
            AwaitingApproval = 45,
            Removing = 66,
            Revalidating = 99,
        }

        static void Main(string[] args)
        {
            Console.WriteLine(GetOrder(ImportState.None));
            Console.WriteLine(GetOrder(ImportState.AwaitingApproval));
        }

        public static int GetOrder(ImportState state)
        {
            var enumValues = Enum.GetValues(typeof(ImportState)).Cast<ImportState>().ToList();

            return enumValues.IndexOf(state) + 1; // +1 as the IndexOf() is zero-based
        }
    }
}

1
3
Press any key to continue . . .

Upvotes: 1

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37113

Sth. like this?

int i = 0;
foreach (ImportState state in Enum.GetValues(typeof(ImportState)))
{
    i++;
    if (state == myState) return i;
}

However there is no real use for this, as enums do not provide an indexed enumeration in themselfes. They represent a value which is more what you´re probably after.

Upvotes: 0

fubo
fubo

Reputation: 46005

here is the missing method GetOrder

public static int GetOrder(ImportState State)
{
    return Enum.GetValues(typeof(ImportState)).Cast<ImportState>().Select((x, i) => new { item = x, index = i }).Single(x => x.item == State).index;
}

Upvotes: 2

Related Questions