ss_blog_claim=049b3d4ff689e7558b5873d1794f7277 Clearing Enum Flags - Brenton House

Brenton House

what are you looking at?

Blog Roll

Stuff

Clearing Enum Flags

 
Via Krzysztof Cwalina -
 

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]

public enum Foos {

    A = 1,

    B = 2,

    C = 4,

    D = 8,

    AB = A | B,

    CD = C | D,

    All = AB | CD

}

 

static class Program {

    static void Main() {

        Foos value = Foos.AB;

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

    }

 

    public static Foos 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.

    public static Foos ClearFlag(Foos value, Foos flag) {

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

        return value;

    }

Or you can manufactore the All value from UInt32.  

    public static Foos 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]

    public enum Foos : ulong {

    }

 

    public static Foos 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.

 
Posted: Aug 29 2006, 09:31 PM by dotnetboy2003 | with 5 comment(s)
Filed under:

Comments

Jason Haley said:

# August 29, 2006 10:45 PM

jonny said:

Isn't it easier to just "and" the compliment of the flag? i.e. value & ~flag

# August 30, 2006 12:48 AM

Paulo Morgado said:

What's wrong with value = (Foos)0?

Shouldn't you be using (Foos)-1 instead (Foos)<whatevertype>.MaxValue?

# August 30, 2006 4:21 AM

Wim said:

Or create an enum value:

None=0,

...

That way it will also be the default if it hasn't been set explicitly. Feels more intuitive to me.

# August 30, 2006 6:27 AM

Clearing Enum Flags said:

Pingback from  Clearing Enum Flags

# November 25, 2007 9:52 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)