2013-03-15 4 views
18

Это определение перечисления:HasFlags всегда возвращает истину None (0) значение в перечислении

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

Теперь, учитывая следующий код, почему обратный метод HasFlag верно для значения Animals.None?

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 документации

, если базовое значение флага равно нулю, то метод возвращает истину

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.

Я лично очень ненавижу методы расширения, но можно было бы разместить это в расширении на Enum, если вы действительно цените возможность писать myOptionEnum.HasNoFlags(). Я бы просто работал с явно проверкой на значение None в этом специальном случае.

Смежные вопросы