8

I am building a fun little app to determine if I should bike to work.

I would like to test to see if it is either Raining or Thunderstorm(ing).

public enum WeatherType : byte
{ Sunny = 0, Cloudy = 1, Thunderstorm = 2, Raining = 4, Snowing = 8, MostlyCloudy = 16 }

I was thinking I could do something like:

WeatherType _badWeatherTypes = WeatherType.Thunderstorm | WeatherType.Raining;
if(currentWeather.Type == _badWeatherTypes)
{
 return false;//don't bike
}

but this doesn't work because _badWeatherTypes is a combination of both types. I would like to keep them separated out because this is supposed to be a learning experience and having it separate may be useful in other situations (IE, Invoice not paid reason's etc...).

I would also rather not do: (this would remove the ability to be configured for multiple people)

if(WeatherType.Thunderstorm)
{
 return false; //don't bike
}
etc...

6 Answers 6

18

Your current code will say whether it's exactly "raining and thundery". To find out whether it's "raining and thundery and possibly something else" you need:

if ((currentWeather.Type & _badWeatherTypes) == _badWeatherTypes)

To find out whether it's "raining or thundery, and possibly something else" you need:

if ((currentWeather.Type & _badWeatherTypes) != 0)

EDIT (for completeness):

It would be good to use the FlagsAttribute, i.e. decorate the type with [Flags]. This is not necessary for the sake of this bitwise logic, but affects how ToString() behaves. The C# compiler ignores this attribute (at least at the moment; the C# 3.0 spec doesn't mention it) but it's generally a good idea for enums which are effectively flags, and it documents the intended use of the type. At the same time, the convention is that when you use flags, you pluralise the enum name - so you'd change it to WeatherTypes (because any actual value is effectively 0 or more weather types).

It would also be worth thinking about what "Sunny" really means. It's currently got a value of 0, which means it's the absence of everything else; you couldn't have it sunny and raining at the same time (which is physically possible, of course). Please don't write code to prohibit rainbows! ;) On the other hand, if in your real use case you genuinely want a value which means "the absence of all other values" then you're fine.

Sign up to request clarification or add additional context in comments.

3 Comments

[Flags] does seem like the way to go here.
Well, it's definitely a good thing to do - but it's entirely orthogonal to the actual question. It will neither help nor hinder the bitwise logic.
You were correct about "Sunny" I needed to change it. Thanks for all the help everyone.
2

I'm not sure that it should be a flag - I think that you should have an range input for:

  • Temperature
  • How much it's raining
  • Wind strength
  • any other input you fancy (e.g. thunderstorm)

you can then use an algorithm to determine if the conditions are sufficiently good.

I think you should also have an input for how likely the weather is to remain the same for cycling home. The criteria may be different - you can shower and change more easliy when you get home.

If you really want to make it interesting, collect the input data from a weather service api, and evaulate the decision each day - Yes, I should have cycled, or no, it was a mistake. Then perhaps you can have the app learn to make better decisions.

Next step is to "socialize" your decision, and see whether other people hear you are making the same decisions.

1 Comment

Aww, I always miss that step!
1

use the FlagsAttribute. That will allow you to use the enum as a bit mask.

21 Comments

You can use the enum as a bitmask without flags; FlagsAttribute just changes how ToString operates, I believe. It would still be a good idea to include it, admittedly.
It does just change how ToString behaves, but there is no guarantee that future versions of .NET won't change other behaviors (like the compiler issuing errors if the values aren't powers of 2) so you should always use it when using a flags enum.
Ah, I didn't know that it just changed the ToString(). Interesting.
If you don't specify the values, Flag will set them appropiately to powers of 2 (at least in VB).
Flags doesn't change the autogenerated values in C#, unfortunately. As for "no guarantee that future versions of .NET won't change other behaviours" - that's like saying "there's no guarantee that the garbage collector will still work in future versions, better set variables to null to help it."
|
0

You need to use the [Flags] attribute (check here) on your enum; then you can use bitwise and to check for individual matches.

1 Comment

Please see my response to MagicKat. Flags is desirable but not necessary here.
0

You should be using the Flags attribute on your enum. Beyond that, you also need to test to see if a particular flag is set by:

(currentWeather.Type & WeatherType.Thunderstorm == WeatherType.Thunderstorm)

This will test if currentWeather.Type has the WeatherType.Thunderstorm flag set.

Comments

0

I wouldn't limit yourself to the bit world. Enums and bitwise operators are, as you found out, not the same thing. If you want to solve this using bitwise operators, I'd stick to just them, i.e. don't bother with enums. However, I'd something like the following:

        WeatherType[] badWeatherTypes = new WeatherType[]
        {   
            WeatherType.Thunderstorm, 
            WeatherType.Raining
        };

        if (Array.IndexOf(badWeatherTypes, currentWeather.Type) >= 0)
        {
                        return false;
        }

1 Comment

This is exactly what flags enums (bit fields) are designed to do. From the MSDN page on the FlagsAttribute: Bit fields are generally used for lists of elements that might occur in combination...Therefore, bit fields are designed to be combined with a bitwise OR operation to generate unnamed values.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.