确定枚举值是否在列表中(C#)
我正在构建一个有趣的小应用程序,以确定我是否应该骑自行车上班。
我想测试一下是下雨还是雷暴。
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; }