确定枚举值是否在列表中(C#)

时间:2020-03-06 15:02:56  来源:igfitidea点击:

我正在构建一个有趣的小应用程序,以确定我是否应该骑自行车上班。

我想测试一下是下雨还是雷暴。

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

我以为我可以做这样的事情:

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

但这不起作用,因为_badWeatherTypes是两种类型的组合。我想将它们分开,因为这应该是一种学习经验,并且将其分开可能在其他情况下有用(例如,IE,发票未付款原因等)。

我也不想这样做:(这将删除为多个人配置的功能)

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

解决方案

使用FlagsAttribute。这样我们就可以将枚举用作位掩码。

我们当前的代码将说明它是否完全是"下雨天"。要确定是否"下着雷雨,可能还有其他事情",我们需要:

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

要确定是"下雨还是打雷,可能还有其他事情",我们需要:

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

编辑(为了完整性):

最好使用FlagsAttribute,即用[[Flags]`装饰类型。出于这种按位逻辑,这不是必需的,但会影响ToString()的行为。 Ccompiler会忽略此属性(至少目前是这样; C3.0规范未提及),但对于有效地标记的枚举而言,通常是个好主意,并且它记录了该类型的预期用途。同时,约定是当我们使用标志时,请将枚举名称复数,以便将其更改为" WeatherTypes"(因为任何实际值实际上都是0或者更多的天气类型)。

还应该考虑" Sunny"的真正含义。当前它的值为0,这意味着没有其他所有内容。我们不能同时下雨天(当然这在物理上是可能的)。请不要编写禁止彩虹的代码! ;)另一方面,如果在实际用例中,我们确实需要一个表示"没有其他所有值"的值,那么我们就可以了。

我们需要在枚举中使用[Flags]属性(在此处检查);那么我们可以按位使用和检查单个匹配项。

我们应该在枚举上使用Flags属性。除此之外,我们还需要测试以查看是否设置了特定标志:

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

这将测试currentWeather.Type是否设置了WeatherType.Thunderstorm标志。

我不会将自己局限于位世界。正如我们发现的那样,枚举和按位运算符不是一回事。如果我们想使用按位运算符解决此问题,我会坚持使用它们,即不要为枚举而烦恼。但是,我想要以下内容:

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

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