如何在其定义列表中获取枚举的数字位置

时间:2014-03-18 11:30:18

标签: c# enums

我需要在其定义中获取枚举的数字位置。 请考虑以下枚举 - 它用于位字段,但用于状态名称 如果他们拥有我评论过的右边的值,那将会非常有用。

[Flags]
public enum StatusFlags
{
    None = 0,                 // 0  -- these commented indexes are the numbers I also would like
    Untested = 1,             // 1     to associate with the enum names.
    Passed_Programming = 2,   // 2
    Failed_Programming = 4,   // 3
    // ... many more
}

我已经创建了一个静态方法,如下所示。

public static int GetStatusID(this StatusFlags flag)
{
   int i = 0;
   foreach (StatusFlags val in Enum.GetValues(typeof(StatusFlags)))
   {
      if (flag == val) break;
      i++;
   }
   return i;
}

它的用法如下:

StatusFlags f = StatusFlags.Failed_Programming;

// I want the position i.e value of 3 not the value the enum is associated with i.e 4
int Index = f.GetStatusID();

有更好的方法吗?

5 个答案:

答案 0 :(得分:3)

你可以这样做:

public static int GetStatusID(this StatusFlags flag)
{
    return
        Enum
            .GetValues(typeof(StatusFlags))
            .Cast<StatusFlags>()
            .Select((f, n) => new { f, n })
            .Where(fn => fn.f == flag)
            .Select(fn => fn.n)
            .DefaultIfEmpty(0)
            .First();
}

答案 1 :(得分:2)

如何在枚举上使用属性?像这样:

[Flags]
public enum StatusFlags
{
    [Index=0]
    None = 0,

    [Index=1]             
    Untested = 1,            

    [Index=2]
    Passed_Programming = 2,

    [Index=3]  
    Failed_Programming = 4,
    // ... many more
}

然后你可以像这样枚举你的枚举的索引值:

var type = typeof(StatusFlags);
var statusFlag = type.GetMember(StatusFlags.Untested.ToString());
var attributes = statusFlag [0].GetCustomAttributes(typeof(IndexAttribute),false);
var index = int.Parse(((IndexAttribute)attributes[0]).Index); //if you need an int value

答案 2 :(得分:1)

这里删除的答案提示了类似

的内容
public static int GetStatusID(this StatusFlags flag)
{
    return Array.IndexOf(Enum.GetValues(typeof(StatusFlags)), flag);
}

并且只是缺少语法点,即IndexOf是Array类中的静态函数,而不是扩展方法。我喜欢它,但为了简洁起见。

答案 3 :(得分:1)

如何使用数学?他说,上升的力量是2

    int GetStatusID(this StatusFlags flag)
    {
        if (((int)flag) == 0) return 0;
        return (Math.Log((double)flag) / Math.Log(2D)) + 1;
    }

答案 4 :(得分:0)

如果每个标志只设置了1位,则索引仅为Math.Log2((int)flag) + 1。但是Math.Log2是浮点运算,并且速度很慢,因此请不要使用它

如果您使用的是.NET Core,则有BitOperations.TrailingZeroCount可以直接映射到x86中的TZCNT / BSF指令或相应体系结构中的类似指令,因此效率更高,结果是这样

public static int GetStatusID(this StatusFlags flag)
{
    if ((int)flag == 0)
        return 0;
    return BitOperations.TrailingZeroCount((int)flag) + 1;
}

如果您使用的是较旧的.NET框架,那么请计算这些问题中的快速计算整数log2的方法