tags:

views:

53

answers:

2

Hi guys, i have this code:

[Flags]
public enum MyUriType {
    ForParse,
    ForDownload,
    Unknown
}

and then:

MyUriType uriType = MyUriType.ForDownload;

but, I was wondering why this returns true:

if ((uriType & MyUriType.ForParse) == MyUriType.ForParse)

When it is not set in the second code group. Please advise.

+7  A: 

By default, the first field for an enum type is given the ordinal value 0.

So, if uriType does not contain the MyUriType.ForParse flag, then uriType & MyUriType.ForParse actually equals 0, which counterintuitively evaluates to true when you compare it to MyUriType.ForParse for equality (which is also 0).

If you break it down to bitwise arithmetic then the expression you're evaluating is:

({something} & 0) == 0

...which will always evaluate to true, no matter what the "something" is.

Normally, when you define a Flags enum, you should actually specify values for each field:

[Flags]
public enum MyUriTypes
{
    None = 0,
    ForParse = 1,
    ForDownload = 2,
    ForSomethingElse = 4,
    ForAnotherThing = 8
}

Each value should be a power of 2 so that they don't conflict (every multiple of 2 is a binary shift-left).

It's also customary to name it as a plural, so that people who use the enum know that it is a Flags enum and can/should hold multiple values.

If you define your enum this way, your test code will now evaluate to false if uriType does not have the ForParse bit set.

Aaronaught
+1 . imaging enum as "expressively magic numbers" :)
Michael Mao
For enums with a lot of fields, you can use hex literals to simplify value assignment: ... ForAnotherThing = 0x8, ForThatOneOtherThing = 0x10, OhYeahAndThatThing = 0x20, etc.
Sam Pearson
Thanks Aaronaught.
Jojo
A: 

You should define it in powers of 2 like:

[Flags]
public enum MyUriType {
None = 0
ForParse = 1,
ForDownload = 2,
Unknown = 4
}

Note that flags are appropriate when you expect a combination of options to be set (e.g. ForParse + Unknown or ForDownload + Unknown). If only one option at a time applies, you can use a regular enum.

Matthew Flaschen