HasFlags总是为枚举中的None(0)值返回true

时间:2013-03-15 15:48:40

标签: c# enums enum-flags

这是枚举定义:

[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

7 个答案:

答案 0 :(得分:30)

HasFlag实际上是这样的:

HasFlag = (GivenFlag & Value) == GivenFlag;

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

答案 1 :(得分:8)

我在自己面前反对这一点。 它是在.NET Framework中设计的:

  

如果flag的基础值为零,则该方法返回true。如果不希望出现这种情况,可以使用Equals方法测试零的相等性,并仅在flag的基础值为非零时调用HasFlag,如下例所示。

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

答案 2 :(得分:2)

已经有大量的答案描述了为什么会发生这种情况,所以我只想补充一点,你能做的就是在这种情况下不要使用HasFlag,而是做{ {1}}。

我个人真的厌恶扩展方法,但是如果你真的很重视能够写var hasNone = myAnimals == Animals.None,那么可以将它放在Enum的扩展名中。我会在这种特殊情况下明确检查myOptionEnum.HasNoFlags()值。

答案 3 :(得分:0)

Enum.HasFlags解析如下:

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

对于零值枚举字段,这总是如此。

答案 4 :(得分:0)

来自 MSDN

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

thisInstance And flag = flag

答案 5 :(得分:0)

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

  

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

答案 6 :(得分:0)

我最终删除了“无”元素。这是一个“魔术值”,会干扰适当的Flags Enum操作(如HasFlag())。

如果没有值,则使用Nullable,即动物? (现在支持基本类型)

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