-1

I would like to pass an argument that says "all", "valid" or "invalid". Instead of going with a nullable bool, I thought that I'd give Flags a shot.

Since I've never used it before, I would like you to sort a few questions out for me:

[Flags]
public enum Options
{
    Valid,
    Invalid
}

private void Foo(Options options)
{
    Debug.WriteLine(string.Format("valid: {0} {1}", 
    (options & Options.Valid) == Options.Valid, 
     options.HasFlag(Options.Valid)));

    Debug.WriteLine(string.Format("invalid: {0} {1}", 
    (options & Options.Invalid) == Options.Invalid, 
     options.HasFlag(Options.Invalid)));

    Debug.WriteLine("---");
}

protected void Page_Load(object sender, EventArgs e)
{
    Foo(Options.Valid | Options.Invalid);
    Foo(Options.Invalid);
    Foo(Options.Valid);
}

/*

Output:

valid: True True
invalid: True True
---
valid: True True
invalid: True True
---
valid: True True
invalid: False False

*/

As you can see, this doesn't give me the desired result. What I would like to know is if either "valid", "invalid" or both flags are set. How would I accomplish that?

Johan
  • 35,120
  • 54
  • 178
  • 293
  • 1
    How can something be `Valid` as well as `InValid` ? Sounds like oxymoron. Btw for flags to work your enum values to be in power of 2. – Sriram Sakthivel Nov 10 '14 at 10:15
  • @SriramSakthivel It's a validation where the users sometimes wants to see all the valid results as well – Johan Nov 10 '14 at 10:16
  • Also [Flags] shows you are using it in this way but it isn't actually required to use the attribute to do so. – CRice Nov 10 '14 at 10:23
  • @CRice yes and no: http://stackoverflow.com/questions/5902967/what-does-the-flags-attribute-really-do –  Nov 10 '14 at 10:38
  • 1
    @Johan be aware that enums start with 0, and your tests failing is due to the nature of "power of 2"... –  Nov 10 '14 at 10:39

1 Answers1

4

For flags you have to assign values so that the boolean operations work as expected:

[Flags]
public enum Options
{
    Valid = (1<<0), // 1
    Invalid = (1<<1), // 2
    All = Valid | Invalid
}

Otherwise your values will be assigned automatically, which would result in Valid=0 and Invalid=1.

As you can see the Valid and Invalid are assigned power of 2 values (eg. 1,2,4,8...). This is needed for the flag test operations to work correctly, as they rely on simple binary operations on the enum values.

To check if both flags are set use:

options.HasFlag(Options.Valid | Options.Invalid)

or

options.HasFlag(Options.All)
Community
  • 1
  • 1
thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
  • 2
    I tend to do it rather like `1 << 0`, `1 << 1`, so that math gets easier (and the bit-position more obvious) ... And combined states rather like `All = Valid | Invalid` ( just in case the bit changes, and again: not doing the math) ... –  Nov 10 '14 at 10:17
  • I see. And if I want to skip `All`? `options.HasFlag(Options.Invalid | Options.Valid)`? – Johan Nov 10 '14 at 10:17
  • @Johan what do you mean by skip? – thumbmunkeys Nov 10 '14 at 10:17
  • How would I check if both `Valid` and `Invalid` is set, without making use of a third flag? – Johan Nov 10 '14 at 10:19
  • 1
    @Johan `options.HasFlag(Options.Invalid) && options.HasFlag(Options.Valid)` ... but for convenience (= less typing) introduction of a combined state is preferred –  Nov 10 '14 at 10:21
  • @AndreasNiedermair Ok. How would I check if both `Valid` and `Invalid` is set without making use of `HasFlags()`? – Johan Nov 10 '14 at 10:22
  • @Johan bit-shifting?! ... c'mon, lmgtfy: eg http://stackoverflow.com/questions/93744/most-common-c-sharp-bitwise-operations-on-enums –  Nov 10 '14 at 10:23
  • @AndreasNiedermair Thanks, wasn't aware of the term – Johan Nov 10 '14 at 10:24
  • @thumbmunkeys you should think about introducing `0`-value for failed conversions, and I **strongly encourage** you to state that the values have to be a power of 2 (due to the *bitish* nature of the shifting/value/whatsoever stuff) –  Nov 10 '14 at 10:25
  • 1
    @Johan just to be precise: bit-shifting is not the specific term for checking if a certain value is contained. the whole thing with `[Flags]` is covered by: shift operators and bitwise operators = bitwise operations –  Nov 10 '14 at 10:30