我有一个这样定义的枚举:
[Flags]
public enum Orientation
{
North = 1,
North_East = 2,
East = 4,
South_East = 8,
South = 16,
South_West = 32,
West = 64,
North_West = 128
}
是否有通用的方法来判断是否设置了一个标志,多个标志还是没有标志? 我不关心枚举的价值,我只想知道设置了多少标志。
这不是用于计算位数的重复。如果我像这样初始化枚举并计算我得到的位数10.但是设置标志的数量将是8。
GeographicOrientation go = (GeographicOrientation) 1023;
答案 0 :(得分:4)
您可以使用此代码:
>>> [str.format('a{0}', x) for x in xrange(1,6)]
['a1', 'a2', 'a3', 'a4', 'a5']
>>> ['a' + str(x) for x in xrange(1,6)]
['a1', 'a2', 'a3', 'a4', 'a5']
答案 1 :(得分:3)
var test = Orientation.North;
var flagCount = GetFlagCount(test);
public int GetFlagCount(Enum testValue)
{
return Enum.GetValues(testValue.GetType()).Cast<Enum>().Count(testValue.HasFlag);
}
答案 2 :(得分:2)
如果您正在寻找&#34;最短的&#34;方式:
Orientation o = Orientation.East | Orientation.West; // o.ToString() = "East, West"
var c = o.ToString().Split().Count();
甚至更短:
var c = (o + "").Split().Count();
<强>更新强>
要支持255以上的值,您可以使用任何丑陋的黑客:
Orientation o = (Orientation) 1023;
var c = ((Orientation)(byte)o + "").Split().Count();
c = ((Orientation)((int)o & 255) + "").Split().Count();
或者只是将枚举定义为byte:
[Flags]
public enum Orientation : byte
{
North = 1,
North_East = 2,
East = 4,
South_East = 8,
South = 16,
South_West = 32,
West = 64,
North_West = 128
}
更新2 我个人不会在生产代码中使用字符串方法,特别是当需要一点位数时。
无论如何,我只是为了好玩而想到了另一个黑客。当设置一位时,Base 2 log将返回一个整数,当0设置时,将返回-Infinity,当设置一位以上时,将返回任何其他内容。例如
Math.Log(0, 2 ) // -Infinity
Math.Log(0, 64) // 6.0
Math.Log(0, 65) // 6.0223678130284544
因此,(byte)go != 0
可用于检查是否设置了任何标志,然后Math.Log((byte)go, 2) % 1 == 0
检查是否只设置了一个标志。
但是,dasblinkenlight的解决方案似乎是最好的。
答案 3 :(得分:1)
脱离我的头顶:
underscored: true
答案 4 :(得分:0)
将值转换为int
后,您可以通过简单的位技巧确定这一点:
int v =(int)enumValue;
v == 0
,则没有设置标志((v-1)&v) == 0
,则只设置一个标志唯一棘手的是#2。以下是一个解释:考虑一个二进制数,其中只有一位设置为1
。然后减去1
将进行以下更改:
0000010000000
- 1
-------------
0000001111111
单独1
后的所有零变为1
s,1
变为零,其余位保持不变。 AND
- v
和v-1
生成零,因为两个数字之间的同一位置没有1
对。
如果有两个或更多1
s,则单独1
左侧的位将保持不变。因此,按位1
的结果中至少有一个位置会有AND
。
答案 5 :(得分:0)
这不是用于计算位数的重复。如果我像这样初始化枚举并计算我得到的位数10.但是设置标志的数量将是8。
请直接考虑此声明from MSDN:
标志枚举用于屏蔽位字段并进行按位比较。
如果您以某种方式设计或使用枚举,不允许使用按位运算计算标志数,那么您正在设计或使用枚举不正确。
[Flags]
public enum MyEnum
{
Foo = 1,
Bar = 2,
Bizz = 4,
Buzz = 8,
Boo = 16
}
var foo = MyEnum.Foo | MyEnum.Foo | MyEnum.Bizz;
// foo == MyEnum.Foo | MyEnum.Bizz because setting the same flag twice does nothing
var bar = (MyEnum)27 // Some invalid combination
// bar == 27. Why would you do this instead of MyEnum.Boo | MyEnum.Buzz | MyEnum.Bar | MyEnum.Foo
如果你正确地设计你的枚举,你可以计算标志,如果设置了多个标志,可以选择短路,因为继续计数将毫无意义。
var foo = MyEnum.Foo | MyEnum.Bizz;
int fooValue = (int)foo;
int numberOfFlags = 0;
while (fooValue > 0 && numberOfFlags < 2) // Stop counting if more than one flag since we don't need exact count
{
if ((fooValue & 1) == 1)
{
numberOfFlags++;
}
fooValue >>= 1;
}
Console.WriteLine(numberOfFlags);