Why should I never use 0 in a flag enum [duplicate]

喜你入骨 提交于 2020-06-12 07:32:30

问题


Possible Duplicate:
Should an Enum start with a 0 or a 1?

Why should I never use 0 in a flag enum? I have read this multiple times now and would like to know the reason :)


回答1:


Because Flag enums are bit collections, or sets of options.

A 0 value would be part of all sets, or of none. It just wouldn't work.




回答2:


Why should I never use 0 in a flag enum?

The question is predicated on an incorrect assumption. You should always use zero in a flag enum. It should always be set to mean "None".

You should never use it for anything other than to represent "none of the flags are set".

Why not?

Because it gets really confusing if zero has a meaning other than "none". One has the reasonable expectation that ((e & E.X) == E.X) means "Is the X flag set?" but if X is zero then this expression will always be true, even if logically the flag is not "set".




回答3:


Although a zero means none of the bits are set, it is often very useful to have a named constant for 0.

When I set up flag words, I define the names of the bits so that they all represent the non-default value. That is, the enum value is always initialised to zero, turning 'off' all the options the bitfield represents.

This provides forwards compatibility for your enum, so that anyone who creates a new value knows that any zero bits are going to be 'safe' to use if you later add more flags to your bitfield.

Similarly it is very useful to combine several flags to make a new constant name, which makes code more readable.

The danger of this (and the reason for the rule you cite) is just that you have to be aware of the difference between single bit values (flags) and values that represent groups or combinations of bits.




回答4:


Flag enums are used like this:

Flag flags = Flag.First | Flag.Next | Flag.Last;

Then you should define your Flag like this:

enum Flag {First = 1, Next = 2, Last = 4};

This way you can see if a Flag has been used e.g.:

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");

This is why you can only use values that is a power of 2 e.g. 1,2,4,8,16,32,64,128,...

If flags is 0 then it is considered blank.

I hope that this will increase your understanding of flag enums.




回答5:


Because typically you use flags as follows:

var myFlagEnum = MyEnum.Foo | MyEnum.Bar | MyEnum.Bat;

// ...  snip ...

if (myFlagEnum & MyEnum.Foo == MyEnum.Foo) { ...  do something ... };

If the MyEnum.Foo were zero, the above wouldn't work (it would return true for all cases). Whereas if it were 1, then it would work.




回答6:


A flag enum assumes that each one of it's values represents the presence of an option and it is coded in one of the enum's bits. So if a particular option is present (or true) the equiveland bit in the enum's value is set (1), otherwise it is not set (0)

so each one of the enum's fields is a value with only one bit set. If none of the options are present or true, then the combined enum's value is zero, which mean none of the bits are set. So the only zero field in a flag's enum, is the one that supposed to mean that no option is set, true, or selected.

For example assume we have a flags enum that encodes the presence of borders in a table cell

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
}

if you want to show that a cell has the top and bottom borders present, then you should use a value of

 Cell.Border = BorderType.Top | BorderType.Bottom; // 0x01 | 0x08 = 0x09 = 00001001 in binary

if you want to show that a cell has no borders present, then you should use a value of

 Cell.Border = BorderType.None; // 0x00 = 00000000 in binary

So you should NEVER use zero as a value for an option in a flag enum, but you should always use zero as the value that means that none of the flags are set.




回答7:


I really don't see the problem.

enum Where {Nowhere=0x00, Left=0x01, Right=0x02, Both=Left|Right};
Where thevalue = Where.Both;
bool result = (thevalue&Where.Nowhere)==Where.Nowhere;

Of course the result is true! What did you expect? Here, think about this.

bool result1 = (thevalue&Where.Left)==Where.Left;
bool result2 = (thevalue&Where.Right)==Where.Right;
bool result3 = (thevalue&Where.Both)==Where.Both;

These are all true! Why should Nowhere be special? There is nothing special about 0!



来源:https://stackoverflow.com/questions/9811047/why-should-i-never-use-0-in-a-flag-enum

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!