2

I have a variable containing some flags and wounder how I'm able to check which flags that are set.

My flags.

[Flags]
    public enum Button{ 
        //Can't have more than 30 flags
        //If an enum is added or deleted need to change for loop in method AddButton

        // Exit flags
        Exit = 1 << 0, 
        Cancel = 1 << 1, 
        Abort = 1 << 2,
        Close = 1 << 3,

        //Proced flags
        Accept = 1 << 4, 
        Ok = 1 << 5,
        Submit = 1 << 6,

        //Question flags
        No = 1 << 7,
        Yes = 1 << 8,

        //Save and load
        Save = 1 << 9,
        SaveAll = 1 << 10,
        SaveNew = 1 << 11,
        Open = 1 << 12,
        Load = 1 << 12
    }

And here are where i check my flags

    for (int i = 1; i <= 12; ++i) {
        if((buttons & 1 << i) == 1 << i){

        }
    }

Apparently I can't use this way to check flags.

To be clear I want to know what flags that are set in buttons.

Update: I can't use the Enum.hasFlag() because I making a game in Unity and it uses Mono. Apparently Mono hasn't support for hasFlag yet.

Olof
  • 776
  • 2
  • 14
  • 33
  • Why can't you do that? Looks like it would work to me, with the exception that you are off by one because you start with `i=1` and shift on top of that, so you can't test for Exit. Granted it isn't very language like in C# but it should do what you want. BTW [Enum.HasFlag](https://msdn.microsoft.com/en-us/library/system.enum.hasflag%28v=vs.110%29.aspx) is the built in way to do that. – Frank J Jun 04 '15 at 17:54
  • I'll get this error " Operator `&' cannot be applied to operands of type `Window.Button' and `int' ". I would love to use Enum.HasFlag but I use Mono and it seams Mono hasn't implemented it yet. – Olof Jun 04 '15 at 18:00
  • Pretty fishy code. it never makes sense to let a button implement multiple operations. It will Save or Open, not both. Remove [Flags]. – Hans Passant Jun 04 '15 at 18:11
  • As @Sam S wrote just cast it. But again this is not very language like – Frank J Jun 04 '15 at 18:13

2 Answers2

2

I pulled this from this article, which is pretty helpful. It shows how to use an enum with bit shifting and bitwise information.

http://www.codeducky.org/ins-outs-c-enums/

// this attribute isn't strictly necessary, but it provides
// useful metadata and greatly improves the ToString() representation
[Flags]
enum BookFlags
{
    // most flags enums provide a named None or Default
    // zero value to represent the empty set
    Default = 0,
    HardCover = 1,
    InStock = HardCover << 1, // 2
    HasEBook = InStock << 1, // 4
    OnSale = HasEBook << 1, // 8
}

// we can create and test flag sets with bitwise operations
BookFlags flags = BookFlags.HardCover | BookFlags.InStock;
var text = flags.ToString(); // HardCover, InStock
var isInStock = (flags & BookFlags.InStock) == BookFlags.InStock; // true
// testing for a particular flag is also simplified by the HasFlag extension
var isInStock2 = flags.HasFlag(BookFlags.InStock); // true

Edit: You probably want something like this, if you can't use HasFlag.

// i redefined your enum a bit
public enum Buttons
{
    // Default
    Default = 0,

    // Exit flags
    Exit = 1,
    Cancel = Exit << 1,
    Abort = Cancel << 1,
    Close = Abort << 1,

    //Proced flags
    Accept = Close << 1,
    Ok = Accept << 1,
    Submit = Ok << 1,

    //Question flags
    No = Submit << 1,
    Yes = No << 1,

    //Save and load
    Save = Yes << 1,
    SaveAll = Save << 1,
    SaveNew = SaveAll << 1,
    Open = SaveNew << 1,
    Load = Open << 1
}

And then you can...

        // here's checking a selection of buttons against the complete enum universe of values
        var lastButton = Convert.ToInt32(Enum.GetValues(typeof(Buttons)).Cast<Buttons>().Max());
        int enumCheck;

        Buttons flags = Buttons.Ok | Buttons.SaveNew | Buttons.Load | Buttons.No | Buttons.Submit | Buttons.Exit;

        for (int i = 0; Math.Pow(2, i) <= lastButton; i++)
        {
            enumCheck = (int)Math.Pow(2, i);

            if ((flags & (Buttons)enumCheck) == (Buttons)enumCheck)
            {
                Debug.WriteLine(Enum.GetName(typeof(Buttons), enumCheck));
            }
        }

Produces output (notice the order):

Exit
Ok
Submit
No
SaveNew
Load
Cortright
  • 1,164
  • 6
  • 19
1

Just cast buttons to int. And you might want to make sure your loop starts with 0, or you'll miss one check.

for (int i = 0; i <= 12; ++i)
{
    if (((int)buttons & 1 << i) == 1 << i)
    {

    }
}
sstan
  • 35,425
  • 6
  • 48
  • 66