2013-03-15 103 views
18

无(0)值为true,这是枚举定义:HasFlags始终返回枚举

现在,考虑下面的代码,为什么该值Animals.None的HasFlag方法的返回真的吗?

Animals myAnimals = Animals.Dog | Animals.Horse; 

var hasNone = myAnimals.HasFlag(Animals.None); //true! Why? 
var hasCat = myAnimals.HasFlag(Animals.Cat);  //false 
var hasDog = myAnimals.HasFlag(Animals.Dog);  //true 
var hasHorse = myAnimals.HasFlag(Animals.Horse); //true 
var hasZebra = myAnimals.HasFlag(Animals.Zebra); //false 

回答

19

HasFlag有效的是这样的:

HasFlag = (GivenFlag & Value) == GivenFlag; 

//"Anything" AND 0 == 0 --> always true 
0

Enum.HasFlags解析为类似如下:

var hasNone = (myAnimals & Animals.None) == Animals.None 

一个零值,枚举场这将永远是正确的。

0

MSDN

的HasFlag方法返回以下布尔表达式的结果。

thisInstance And flag = flag 
0

这只是HasFlag方法的定义行为。从MSDN文档

如果标志的基础值是零,该方法返回true

6

我碰到这个自己之前。 它是在.NET Framework中设计的:

如果标志的基础值为零,则该方法返回true。如果这种行为不可取,那么您可以使用Equals方法来测试是否等于零,并且只有在标记的基础值非零时才调用HasFlag,如以下示例所示。

您可以在MSDN文章在这里读多一点关于这一点:http://msdn.microsoft.com/en-GB/library/system.enum.hasflag.aspx

2

已经有说明为什么出现这种情况的答案过多,所以我只想补充一点,你可以做什么得到什么你正在寻找的是在这种情况下不使用HasFlag,而是var hasNone = myAnimals == Animals.None

我个人确实不喜欢扩展方法,但是如果你真的有能力只写myOptionEnum.HasNoFlags()就可以把它放在Enum的扩展名上。不过,我会在明确检查None值的情况下运行。