我需要得到枚举定义中的数字位置。考虑下面的enum -它用于位字段,但用于状态名如果它们的右边有我注释过的值,
[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();
有更好的方法吗?
如何在枚举上使用属性?像这样:
[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
这里的一个被删除的答案暗示了一些类似
的东西public static int GetStatusID(this StatusFlags flag)
{
return Array.IndexOf(Enum.GetValues(typeof(StatusFlags)), flag);
}
,只是遗漏了语法要点,即IndexOf是Array类中的静态函数,而不是扩展方法。我喜欢它,因为它简洁。
你可以这样做:
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();
}
直接用数学怎么样?他说旗子以2的幂上升
int GetStatusID(this StatusFlags flag)
{
if (((int)flag) == 0) return 0;
return (Math.Log((double)flag) / Math.Log(2D)) + 1;
}
如果每个标志只设置了1位,那么索引就是Math.Log2((int)flag) + 1
。但是Math.Log2
是一个浮点运算,非常慢所以不要使用它
如果你使用。net Core,那么有BitOperations.Log2
和BitOperations.TrailingZeroCount
直接映射到硬件指令,如x86中的TZCNT/BSF或ARM中的CLZ,因此更有效,结果是这样的
public static int GetStatusID(this StatusFlags flag)
{
if ((int)flag == 0)
return 0;
return BitOperations.Log2((int)flag);
// or return BitOperations.TrailingZeroCount((int)flag) + 1;
}
如果你使用的是一个较旧的。net框架,那么计算看看在这些问题中快速计算整数log2的方法
- 在c#中计算整数log2的最快方法是什么?
- log2(int)和log2(float)的最快实现
- 在64位整数 中查找最高和最低有效位集的快速方法