6

I have an enumeration with flags. I want to declare a variable with n different flags. n > 1 in this case.

public enum BiomeType {
    Warm = 1,
    Hot = 2,
    Cold = 4,
    Intermediate = 8,

    Dry = 16,
    Moist = 32,
    Wet = 64,
}

Okay - one variant is to cast each flag into an byte and cast the result to my enum.

BiomeType bType = (BiomeType)((byte)BiomeType.Hot + (byte)BiomeType.Dry)

But this is kinda messy - imho. Is there an more readable way to combine flags?

boop
  • 7,413
  • 13
  • 50
  • 94
  • You can find an amazing overview about enum flags here: http://stackoverflow.com/a/8480/2822719 Using the `[Flags]` attribute will also get you a nicer representation of `BiomeType.ToString()` (i.e. `Hot, Dry` instead of `18` for `BiomeType.Hot | BiomeType.Dry`) – Marcus Mangelsdorf Feb 04 '16 at 10:31

3 Answers3

10

Simple, use the binary "or" operator:

BiomeType bType = BiomeType.Hot | BiomeType.Dry;

Also, if the values can be combined like this it's best to mark the enum with the Flags attribute to indicate this:

[Flags]
public enum BiomeType {
    Warm = 1,
    Hot = 2,
    Cold = 4,
    Intermediate = 8,
    Dry = 16,
    Moist = 32,
    Wet = 64,
}

Adding enumeration values is bad for a number of reasons. It makes it easy to produce a value that is outside the defined values, i.e.:

BiomeType bType = (BiomeType)((byte)BiomeType.Wet + (byte)BiomeType.Wet);

While contrived, this example yields a value of 128, which doesn't map to a known value. This will still compile and run, but it's likely you didn't build your code to handle values outside of those defined and could lead to undefined behavior. However, if you use the pipe (or "binary or") operator:

BiomeType bType = BiomeType.Wet | BiomeType.Wet;

The result is still just BiomeType.Wet.

Furthermore, using addition like in your question provides no Intellisense in the IDE which makes using the enumeration unnecessarily more difficult.

Community
  • 1
  • 1
Patrick Quirk
  • 23,334
  • 2
  • 57
  • 88
  • 1
    You should also mark the enum with `[Flags]`, since that's what you're using it as. – Blorgbeard Aug 18 '14 at 20:58
  • 1
    Much better, great answer! – BradleyDotNET Aug 18 '14 at 21:10
  • 1
    One additional note - when adding the `[Flags]` attribute to an enumeration, .Net naming convention recommends you adjust the name to be plural - in this case `BiomeTypes`. See http://msdn.microsoft.com/en-us/library/4x252001(v=vs.71).aspx . – Gjeltema Aug 23 '14 at 13:56
4

Add the [Flags] attribute to your enum. Then you can just mask them:

[Flags]
public enum BiomeType
{
    Warm = 1,
    Hot = 2,
    Cold = 4,
    Intermediate = 8,

    Dry = 16,
    Moist = 32,
    Wet = 64,
}

BiomeType bType = BiomeType.Hot  | BiomeType.Dry;

(Actually you can mask then without the flags attribute, but you should add it for clarity.)

You can even do something like this to combine all the flags:

var allBiomeTypes = ((BiomeType[])Enum.GetValues(typeof(BiomeType))).Aggregate((BiomeType)0, (a, c) => a | c);
dbc
  • 104,963
  • 20
  • 228
  • 340
3

Use the | (bitwise or) operator. You get IntelliSense support for this. (The other bitwise operators function the same as they do on the underlying numeric type.)

var bType = BiomeType.Hot | BiomeType.Dry;

You should also use the [Flags] attribute as a hint on the enum definition:

[Flags]
public enum BiomeType
{
    Warm = 1,
    Hot = 2,
    Cold = 4,
    Intermediate = 8,

    Dry = 16,
    Moist = 32,
    Wet = 64,
}

(For an explanation, see What does the [Flags] Enum Attribute mean in C#?)

jnm2
  • 7,960
  • 5
  • 61
  • 99