【发布时间】:2012-03-21 18:56:53
【问题描述】:
【问题讨论】:
-
我想知道你在哪里读到的以及你为什么这么说......
-
除了表示一个未设置的值外,你不应该使用它
-
您应该只将它用于
None选项。 -
@ChrisShain 不,不是。把你的事实弄清楚。 1&2 为 0。
【问题讨论】:
None 选项。
为什么我不应该在标志枚举中使用 0?
这个问题是基于一个不正确的假设。您应该始终在标志枚举中使用零。它应始终设置为“无”。
除了表示“未设置任何标志”之外,您不应将其用于任何其他用途。
为什么不呢?
因为如果零具有“无”以外的含义,它会变得非常混乱。人们有合理的期望,((e & E.X) == E.X) 的意思是“X 标志设置了吗?”但如果 X 为零,则此表达式将始终为真,即使 逻辑上标志未“设置”。
【讨论】:
因为标志枚举是位集合或选项集。
0 值将是所有集合的一部分,或者不属于任何集合。它只是行不通。
【讨论】:
None 命名值有时会很有用。
虽然零表示没有设置任何位,但为 0 指定一个命名常量通常非常有用。
当我设置标志字时,我定义了位的名称,以便它们都代表非默认值。也就是说,枚举值始终初始化为零,从而“关闭”位域表示的所有选项。
这为您的枚举提供了前向兼容性,因此创建新值的任何人都知道,如果您以后向位域添加更多标志,任何零位都将是“安全”的。
同样,将多个标志组合成一个新的常量名称也非常有用,这使代码更具可读性。
这样做的危险(以及您引用规则的原因)只是您必须了解单个位值(标志)和表示位组或位组合的值之间的差异。
【讨论】:
标志枚举是这样使用的:
Flag flags = Flag.First | Flag.Next | Flag.Last;
那么你应该像这样定义你的标志:
enum Flag {First = 1, Next = 2, Last = 4};
这样你就可以看到一个标志是否被使用了,例如:
if (flags & Flag.First <> 0) Console.WriteLine("First is set");
if (flags & Flag.Next <> 0) Console.WriteLine("Next is set");
if (flags & Flag.Last <> 0) Console.WriteLine("Last is set");
这就是为什么您只能使用 2 的幂的值,例如1,2,4,8,16,32,64,128,...
如果 flags 为 0,则视为空白。
我希望这会增加你对标志枚举的理解。
【讨论】:
因为通常您使用如下标志:
var myFlagEnum = MyEnum.Foo | MyEnum.Bar | MyEnum.Bat;
// ... snip ...
if (myFlagEnum & MyEnum.Foo == MyEnum.Foo) { ... do something ... };
如果 MyEnum.Foo 为零,则上述内容将不起作用(在所有情况下都将返回 true)。而如果它是 1,那么它会起作用。
【讨论】:
& 而不是逻辑与运算符 &&。
一个标志枚举假定它的每个值都代表一个选项的存在,并且它被编码在枚举的一个位中。因此,如果存在特定选项(或为真),则枚举值中的 equiveland 位设置为 (1),否则不设置 (0)
所以枚举的每个字段都是一个只设置了一个位的值。如果没有任何选项存在或为真,则组合枚举的值为零,这意味着没有设置任何位。因此,标志枚举中唯一的零字段应该意味着没有设置、为真或选择任何选项。
例如,假设我们有一个标志枚举,它编码表格单元格中边框的存在
public enum BorderType
{
None = 0x00, // 00000000 in binary
Top = 0x01, // 00000001 in binary
Left = 0x02, // 00000010 in binary
Right = 0x04, // 00000100 in binary
Bottom = 0x08 // 00001000 in binary
}
如果你想显示一个单元格有上下边框,那么你应该使用值
Cell.Border = BorderType.Top | BorderType.Bottom; // 0x01 | 0x08 = 0x09 = 00001001 in binary
如果你想显示一个单元格没有边框,那么你应该使用值
Cell.Border = BorderType.None; // 0x00 = 00000000 in binary
所以你不应该在标志枚举中使用零作为选项的值,但你应该始终使用零作为值,这意味着没有设置任何标志。
【讨论】:
我真的没有看到问题。
enum Where {Nowhere=0x00, Left=0x01, Right=0x02, Both=Left|Right};
Where thevalue = Where.Both;
bool result = (thevalue&Where.Nowhere)==Where.Nowhere;
当然结果是真的!你期待什么?在这里,考虑一下。
bool result1 = (thevalue&Where.Left)==Where.Left;
bool result2 = (thevalue&Where.Right)==Where.Right;
bool result3 = (thevalue&Where.Both)==Where.Both;
这些都是真的!为什么Nowhere 要特别? 0没什么特别的!
【讨论】:
nowhere & left == nowhere,而left & right == both。
& 的工作方式仍然有误。查找它,或在您自己的编译器上测试它。 left & right 真的是 0。老实说。