Ответ 1
HasFlag
эффективно это:
HasFlag = (GivenFlag & Value) == GivenFlag;
//"Anything" AND 0 == 0 --> always true
Это определение перечисления:
[Flags]
enum Animals
{
None = 0,
Dog = 1,
Cat = 2,
Horse = 4,
Zebra = 8,
}
Теперь, учитывая следующий код, почему метод HasFlag возвращает true для значения 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
HasFlag
эффективно это:
HasFlag = (GivenFlag & Value) == GivenFlag;
//"Anything" AND 0 == 0 --> always true
Я столкнулся с этим перед собой. Он по дизайну в .NET Framework:
Если базовое значение флага равно нулю, метод возвращает true. Если это поведение нежелательно, вы можете использовать метод Equals для проверки равенства с нулем и вызывать HasFlag только в том случае, если базовое значение флага не равно нулю, как показано в следующем примере.
Вы можете прочитать немного больше об этом в статье MSDN здесь: http://msdn.microsoft.com/en-GB/library/system.enum.hasflag.aspx
Уже есть множество ответов, описывающих ПОЧЕМУ это происходит, поэтому я просто добавлю, что то, что вы можете сделать, чтобы получить то, что вы ищете, - это не использовать HasFlag
в этом случае, а вместо этого var hasNone = myAnimals == Animals.None
,
Я лично очень ненавижу методы расширения, но можно было бы разместить это в расширении на Enum
, если вы действительно цените возможность писать myOptionEnum.HasNoFlags()
. Я просто запускал бы с явной проверкой значения None
в этом специальном случае.
Ну Enum.HasFlags
разрешается как-то вроде следующего:
var hasNone = (myAnimals & Animals.None) == Animals.None
Это всегда будет верно для поля с нулевым значением-enum.
От MSDN
Метод HasFlag возвращает результат следующего булевого выражения.
thisInstance And flag = flag
Это всего лишь определенное поведение метода HasFlag
. Из MSDN документация
если базовое значение флага равно нулю, метод возвращает true