2015-06-15 45 views
0

如果我有枚举:如何获得枚举订单?

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

如何获得枚举订单? 例如:

GetOrder(ImportState.None) 

应该返回1(第一顺序)

GetOrder(ImportState.AwaitingApproval) 

应返回3(第三按顺序)

+7

你不应该把枚举想象成有序的,因为它可能会导致代码行不正确。你试图实现什么? – Sayse

+0

进一步证明Sayse的观点,下面的答案只有在枚举值按数字升序定义时才有效。否则,例如,如果您定义了“无= 100”,则无法正确获取常量的顺序。 – sstan

+0

我的枚举是所有导入状态的一些工作流。我想根据这个枚举创建进度条。所以如果我在枚举中有10个值,并且前3个已完成,那么在我的进度条中,这个值就是30%。我的枚举不能有正常的顺序1,2,3 ..,因为将来可能会包含新的枚举值。 – Raskolnikov

回答

2

这里是缺少方法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; 
} 
+0

好的,简单的,干净的回答问题。谢谢。 – Raskolnikov

0

STH。喜欢这个?

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

然而,这并没有真正的用处,因为枚举不提供索引枚举本身。它们代表了一种更可能是你以后的价值。

+0

是的!但我认为有更清洁的东西。 – Raskolnikov

+2

'Enum.GetValues(typeof(ImportState))'不注意代码中的行顺序并将枚举值从最小值列表到最大值。看到演示https://dotnetfiddle.net/AfwNtt – ASh

+0

你是什么意思的“更清洁”。此外,我想我们中的任何一个人都感兴趣为什么你需要有序枚举中的索引号。 – HimBromBeere

0

你可以使用这个LINQ查询:

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

它的订单由枚举值的整型值,那么它需要所有,直到搜索值并对它们进行计数。我省略了OrderBy,因为Enum.GetValues根据它们的int值自动返回订单。

MSDN

该阵列的元件由 枚举的二进制值进行排序常数

+0

值可能不是递增顺序。从问题中不清楚,这是OP所需要的,因为OP可能需要按照它们指定的顺序值。 – DavidG

+0

@DavidG:由于OP指定了那些不寻常的值,我怀疑这是他想要的。否则它无论如何都不合理。 –

+0

我同意这可能是他想要的,我只是认为它是目前的形式,这是一个糟糕的问题。 – DavidG

1

枚举枚举值,转换成一IEnumerable,转换为List。这是使用IndexOf()的简单问题。

注意,对于这项工作,枚举必须以递增的顺序声明。

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 . . . 
2

作为其它注意到的,Enum.GetValues()返回由值排序枚举的值。也许,这是不是你想要的......所以,用一点点反思:

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

使用示例:

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

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

注意,C#规格尚不清楚,如果“源代码“在编译的程序中维护enum的排序......此时C#编译器似乎仍然保留它,但未来无法保证...

只有两个引用我发现是:永远不会需要在C#

前向声明,因为除了极少数例外情况,声明顺序无关紧要

当省略常量表达式值时,枚举成员声明(§14.3)的声明顺序很重要。

因此,正如我写的,我给出的例子,排序是未定义的,取决于C#编译器!

0

而不是使用顺序,你会更好地使用标志。考虑以下

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

Example

枚举真的没有订购任何意义,使用上述可能仍然是不完美的,但它不涉及由顺序。