Clearing Enum Flags

Somebody just pointed out to me that the enum guidelines don’t provide any information on how to clear a flag in a flags enum variable.

This is quite easy to do if the enum has a value (member) that has all the flags set. Such value is usually called All.

[Flags]

publicenumFoos {

A = 1,

B = 2,

C = 4,

D = 8,

AB = A | B,

CD = C | D,

All = AB | CD

}

staticclassProgram {

staticvoid Main() {

Foos value = Foos.AB;

Console.WriteLine(ClearFlag(value,Foos.A);

}

publicstaticFoos ClearFlag(Foos value, Foos flag) {

value = value & (Foos.All ^ flag);

return value;

}

}

If the enum does not contain the All value, you can manually create it by combining existing flags.

publicstaticFoos ClearFlag(Foos value, Foos flag) {

value = value & ((Foos.AB|Foos.CD) ^ flag);

return value;

}

Or you can manufactore the All value from UInt32.

publicstaticFoos ClearFlag(Foos value, Foos flag) {

Foos all;

unchecked {

all = (Foos)UInt32.MaxValue;

}

value = value & (all ^ flag);

return value;

}

Keep in mind that not all enums are backed with 32-bit integers. For these that are larger, for example enums with ulong as the underlying type, you will need to use UINt32.MaxValue instead.

[Flags]

publicenumFoos : ulong {

…

}

publicstaticFoos ClearFlag(Foos value, Foos flag) {

Foos all;

unchecked {

all = (Foos)UInt64.MaxValue;

}

value = value & (all ^ flag);

return value;

}

What’s interesting is that you don’t actually need to change anything if the underlying type is smaller, i.e. you can cast UInt64 to an enum backed with a byte. The cast operator takes care of the size mismatch. This means you could always use UInt64. The only drawback would be that it makes the variable all larger than it has to be, which is a slight inefficiency, probably not detectable in all but the most targeted benchmarks.