tags:

views:

5435

answers:

11

Anyone have a good explanation or example they could post?

Edit: I changed the answer, this one is more in depth.

+3  A: 
Jay Mooney
A: 

Definition

[Flags] 
public enum Color 
{  
    Red, White, Blue
}

Usage

Color norwegianFlag = Color.Red | Color.White | Color.Blue

Use the [Flags] attribute to specify that you can combine its members.

Further reading: Enum values as bit flags - using FlagsAttribute

Christian Hagelid
@Christian: you have to explicitely specify the values of a flags enumeration if you want something sensible; with your example, Red=0, White=1 and Blue=2. You should assign power of two values (0x01, 0x02, 0x04, 0x08, 0x10, etc.) and include a `None` value of zero. The blog post you are referring to is mistaken; follow the discussions going on there. Or try it out for yourself...
Pierre
+11  A: 

Please see the following for an example which shows the declaration and potential usage:

namespace Flags
{
    class Program
    {

        [FlagsAttribute]
        public enum MyFlags : short
        {
            Foo = 0x1,
            Bar = 0x2,
            Baz = 0x4
        }

        static void Main(string[] args)
        {
            MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;

            if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
            {
                Console.WriteLine("Item has Foo flag set");
            }
        }
    }
}
OJ
+27  A: 

You can also do this

[Flags]
public enum MyEnum
{
    None = 0,
    First = 1,
    Second = 1 << 1,
    Third = 1 << 2,
    Fourth = 1 << 3
}

I find the bit-shifting easier than typing 4,8,16,32 and so on. It has no impact on your code because it's all done at compile time

Orion Edwards
Thanks, that's great!!
abatishchev
that is very nice
Robert MacLean
And the first time ever to use the << for a valid reason. Cool Thanks
Miau
+48  A: 

The flags attribute should be used only when bitwise operations (and, or, exclusive or, not) is to be used on the enum. One example is

myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

This will render the posibility to retrieve these three distinct values from your property AllowedColors.

For this to work the values in your enumeration need to be powers of two (as seen in Jay Mooneys example)

[Flags]
public enum MyColor
{
    Yellow = 1,
    Green = 2,
    Red = 4,
    Blue = 8
}

To retrieve the distinct values in you property one can do this

if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
    // Yellow has been set...
}

if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
    // Green has been set...
}

Under the covers

This works because you previously used multiples of two in you enumeration. Under the covers your enumeration values looks like this (presented as bytes, which has 8 bits which can be 1's or 0's)

 Yellow: 00000001
 Green:  00000010
 Red:    00000100
 Blue:   00001000

Likewise, after you've set your property AllowedColors to Red, Green and Blue (which values where OR'ed by the pipe |), AllowedColors looks like this

myProperties.AllowedColors: 00001110

So when you retreive the value you are actually bitwise AND'ing the values

myProperties.AllowedColors: 00001110
             MyColor.Green: 00000010
             -----------------------
                            00000010 // Hey, this is the same as MyColor.Green!

The None = 0 value

And regarding use 0 in you enumeration, quoting from msdn:

[Flags]
public enum MyColor
{
    None = 0,
    ....
}

Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.

You can find more info about the flags attribute and its usage at msdn and designing flags at msdn

Andreas H.R. Nilsson
As OJ pointed out, the values need to be powers of two, not multiples. Please update your answer
Oskar
Also, I don't get what the Flags attribute really does? I seem to be able to define and use my flags enum just fine without the attribute. Is it merely used as indication that the enum can be used as flags?
Oskar
Flags itself does nothing. Also, C# does not require Flags per se. But the `ToString` implementation of your enum uses Flags, and so does `Enum.IsDefined`, `Enum.Parse`, etc. Try to remove Flags and look at the result of MyColor.Yellow | MyColor.Red; without it you get "5", with Flags you get "Yellow, Red". Some other parts of the framework also use [Flags] (e.g., XML Serialization).
Ruben
+1  A: 
Nidonocu
+1  A: 

To add Mode.Write:

Mode = Mode | Mode.Write;
Ch00k
or Mode |= Mode.Write
abatishchev
+1  A: 

@Nidonocu

To add another flag to an existing set of values, use the OR assignment operator.

Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
  && ((Mode & Mode.Read) == Mode.Read)));
steve_c
+5  A: 

I asked recently about something similar.

If you use flags you can add an extension method to enums to make checking the contained flags easier (see post for detail)

This allows you to do:

[Flags]
public enum PossibleOptions : byte
{
    None = 0,
    OptionOne = 1,
    OptionTwo = 2,
    OptionThree = 4,
    OptionFour = 8,

    //combinations can be in the enum too
    OptionOneAndTwo = OptionOne | OptionTwo,
    OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
    ...
}

Then you can do:

PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree 

if( opt.IsSet( PossibleOptions.OptionOne ) ) {
    //optionOne is one of those set
}

I find this easier to read than the most ways of checking the included flags.

Keith
IsSet is an extension method I assume?
Robert MacLean
Yeah - read the other question that I link to for details: http://stackoverflow.com/questions/7244
Keith
.NET 4 adds a `HasFlag` method to enumerations, so you can do `opt.HasFlag( PossibleOptions.OptionOne )` without having to write your own extensions
Orion Edwards
+5  A: 

For this to work the values in your enumeration need to be multiples of two

This is not correct. The values need to be powers of two.

OJ
+1  A: 

What am I missing here? Since enum's are (per default) using int to store the value, standard bitwise operations have always worked without [flags], like this:

    enum MyEnum
    {
        enum1 = 1,
        enum2 = 2,
        enum4 = 4
    }
    private void testBitwiseEnums()
    {
        MyEnum result = MyEnum.enum1 | MyEnum.enum2;

        if ((result & MyEnum.enum2) == MyEnum.enum2)
        {
            //this will happen
        }

        if ((result & MyEnum.enum4) == MyEnum.enum4)
        {
            //this will NOT happen
        }

        result |= MyEnum.enum4;
        if ((result & MyEnum.enum4) == MyEnum.enum4)
        {
            //this will happen
        }

        result &= ~MyEnum.enum4;
        if ((result & MyEnum.enum4) == MyEnum.enum4)
        {
            //this will NOT happen
        }
    }

no?

joeriks