31

这是枚举定义:

[Flags]
enum Animals
{
    None = 0,
    Dog = 1,
    Cat = 2,
    Horse = 4,
    Zebra = 8,
}

现在,给定以下代码,为什么 HasFlag 方法对 Animals.None 值返回 true?

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
4

7 回答 7

48

HasFlag实际上是这样的:

HasFlag = (GivenFlag & Value) == GivenFlag;

//"Anything" AND 0 == 0  --> always true
于 2013-03-15T15:51:16.937 回答
10

我自己之前就遇到过这个问题。它是在 .NET Framework 中设计的:

如果 flag 的基础值为零,则该方法返回 true。如果此行为不可取,您可以使用 Equals 方法测试是否与零相等,并仅在 flag 的基础值非零时调用 HasFlag,如下例所示。

您可以在此处的 MSDN 文章中阅读更多相关信息:http: //msdn.microsoft.com/en-GB/library/system.enum.hasflag.aspx

于 2013-03-15T15:52:14.003 回答
2

已经有很多答案描述了为什么会发生这种情况,所以我只想补充一点,你可以做的就是HasFlag在这种情况下不使用,而是使用var hasNone = myAnimals == Animals.None.

我个人真的很讨厌扩展方法,但是Enum如果你真的很重视能够只写myOptionEnum.HasNoFlags(). None不过,在这种特殊情况下,我将只运行显式检查值。

于 2016-02-03T12:05:46.300 回答
0

很好Enum.HasFlags解决如下:

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

对于零值枚举字段,这始终是正确的。

于 2013-03-15T15:51:23.137 回答
0

来自MSDN

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

thisInstance And flag = flag
于 2013-03-15T15:51:45.270 回答
0

这只是该HasFlag方法的定义行为。来自MSDN文档

如果 flag 的基础值为零,则该方法返回 true

于 2013-03-15T15:52:00.743 回答
0

我最终删除了“无”元素。它是一个“神奇值”,会干扰正确的 Flags Enum 操作(如 HasFlag())。

如果没有价值,那么使用 Nullable 即动物?(现在支持原始类型)

编辑:我需要一个“默认”值(非零)用于可序列化对象,以避免使用 Nullable(与业务逻辑冲突)。但我认为这仍然比使用'None = 0'更好。

于 2020-07-02T23:06:14.870 回答