【发布时间】:2019-06-30 08:09:28
【问题描述】:
枚举的Flags attribute 允许该枚举类型的变量通过位逻辑获取多个值。这就是为什么建议每个枚举成员都有一个数值,它是 2 或 0 的幂。
但是 C# 并没有阻止您定义一个值为 3 的成员。
这引发了一个问题 - C# 如何组合具有数值不是 0 或 2 的成员的标志?
例如,一个普通的标志枚举会产生类似的东西(取自上面的 MSDN 链接):
// Define an Enum with FlagsAttribute.
[Flags]
enum MultiHue : short
{
None = 0,
Black = 1,
Red = 2,
Green = 4,
Blue = 8
};
static void Main( )
{
// Display all combinations of values, and invalid values.
Console.WriteLine("\nAll possible combinations of values with FlagsAttribute:");
for( int val = 0; val <= 16; val++ )
Console.WriteLine( "{0,3} - {1:G}", val, (MultiHue)val);
}
// All possible combinations of values with FlagsAttribute:
// 0 - None
// 1 - Black
// 2 - Red
// 3 - Black, Red
// 4 - Green
// 5 - Black, Green
// 6 - Red, Green
// 7 - Black, Red, Green
// 8 - Blue
// 9 - Black, Blue
// 10 - Red, Blue
// 11 - Black, Red, Blue
// 12 - Green, Blue
// 13 - Black, Green, Blue
// 14 - Red, Green, Blue
// 15 - Black, Red, Green, Blue
// 16 - 16
但是,如果我将另一个成员添加到“MultiHue”枚举中,数值为“3”,则会产生以下结果:
// Define an Enum with FlagsAttribute.
[Flags]
enum MultiHue : short
{
None = 0,
Black = 1,
Red = 2,
Lime = 3,
Green = 4,
Blue = 8
};
static void Main( )
{
// Display all combinations of values, and invalid values.
Console.WriteLine("\nAll possible combinations of values with FlagsAttribute:");
for( int val = 0; val <= 16; val++ )
Console.WriteLine( "{0,3} - {1:G}", val, (MultiHue)val);
}
0 - None
1 - Black
2 - Red
3 - Lime
4 - Green
5 - Black, Green
6 - Red, Green
7 - Lime, Green
8 - Blue
9 - Black, Blue
10 - Red, Blue
11 - Lime, Blue
12 - Green, Blue
13 - Black, Green, Blue
14 - Red, Green, Blue
15 - Lime, Green, Blue
16 - 16
注意不同的组合如何用不同的成员表示,例如:
4 是“绿色”,但也可以是“石灰,黑色”
7 是“Lime, Green”,而不是之前的“Black, Red, Green”
等等
我知道这是一种不好的做法,但我想知道编译器如何决定将哪些成员组合用于某个位组合?
【问题讨论】:
-
这里的方法很简单;它首先查找完全匹配,然后查找具有相同值的按位组合;但是 - 这很重要 - 认为 3===Lime 作为一种颜色是非常错误的;您实际上所做的是将“Lime”定义为Black/Red 组合的别名。按位数学用 [Flags] 统治一天。还有青柠===3===(1|2)===(黑|红)。
-
旁注:4 绝对不是“石灰,黑色”; "Lime, Black" 将是 3|1,即 3,而不是 4;组合标志时不要添加;你或(按位)
-
@MarcGravell 您的评论实际上是最好的答案。至于旁注:D'oh!当然你是对的,它只是让我忘记了。 :)
标签: c# enums bit-manipulation bitflags