Должен "или" работать с.Net4 Hasflags: enum.HasFlag(AccessRights.Read | AccessRights.Write)
Я опробовал новые функции HasFlags, и мне было интересно, должно ли работать следующее:
enum.HasFlag (AccessRights.Read | AccessRights.Write)
... потому что это не похоже...
DBAccessRights rights = (DBAccessRights)permission.PermissionFlags;
if (rights.HasFlag(DBAccessRights.WikiMode))
{
// works
}
if (rights.HasFlag(DBAccessRights.WikiMode | DBAccessRights.CreateNew))
{
// Doesn't work
}
DBAccessRights flags = DBAccessRights.WikiMode | DBAccessRights.CreateNew;
if (rights.HasFlag(flags))
{
// Doesn't work
}
6 ответов
Учитывая документацию, я ожидаю, что она вернет true, если значение имеет оба этих флага.
Если вы хотите проверить, имеет ли ваше значение какой- либо из этих флагов, вам понадобится
value.HasFlag(AccessRights.Read) | value.HasFlag(AccessRights.Write)
Если это не достаточно хорошо читается для вас, вы можете посмотреть на мой проект Unconstrained Melody. Так получилось, что он уже обладает нужной вам функциональностью (в качестве методов расширения в Flags.cs
):
// Same as value.HasFlag(AccessRights.Read | AccessRights.Write)
value.HasAll(AccessRights.Read | AccessRights.Write)
// Same as value.HasFlag(AccessRights.Read) | value.HasFlag(AccessRights.Write)
value.HasAny(AccessRights.Read | AccessRights.Write)
Это сделало бы это более понятным, ИМО. Они также избегали бы бокса и были бы в безопасности:)
Из MSDN:
Метод HasFlag возвращает результат следующего логического выражения.
thisInstance И флаг = флаг
Для сложного флага, такого как AccessRights.Read | AccessRights.Write
, это проверит, что присутствуют все "содержащиеся" флаги.
Вы, вероятно, хотите проверить наличие любого из флагов, и в этом случае вы можете сделать:
myAccessRights & (AccessRights.Read | AccessRights.Write) != 0
|
Оператор побитовый или. Это означает, что если Read
это 1 и Write
2, значение Read | Write
3 (см. его двоичное представление). Так HasFlag
возвращает true, только если ваш enum
переменная имеет оба Read
а также Write
задавать.
В качестве альтернативы, вы можете просто изменить порядок выражения:
//returns true - a bit easier on the eye
(AccessRights.Read | AccessRights.Write).HasFlag(myAccessRights)
Это вернет истину, если у вас есть чтение | Доступ для записи. Это было бы функционально эквивалентно:
//also returns true - as per @Ani's answer
myAccessRights & (AccessRights.Read | AccessRights.Write) != 0
РЕДАКТИРОВАТЬ
Как указано в комментариях, первое выражение вернет true, если myAccessRights пусто, и false, если myAccessRights имеет больше, чем просто чтение и запись.
В помеченном перечислении вы можете просто сделать:
(MyEnum01 & MyEnum02) != 0
Если есть какие - либо общие биты, бит будет установлено и , таким образом , число больше не 0. Если нет нет общих бит, результат равен 0. Для этого помеченного перечисление на 0 не должно представлять «нет».
Вот статический метод для общих перечислений и один для конкретного:
public static partial class UtilityMethods
{
public static bool HasAnyFlags (Enum enumA, Enum enumB)
{
return ((int) (object) enumA & (int) (object) enumB) != 0;
}
public static bool HasAnyFlags (MyEnum enumA, MyEnum enumB)
{
return (enumA & enumB) != 0;
}
}
Вы также можете создать свой собственный метод расширения:
public static partial class ExtensionMethods
{
public static bool HasAnyFlag (this Enum e, Enum compared)
{
return ((int) (object) e & (int) (object) compared) != 0;
}
}
Для общих перечислений я взял преобразование отсюда . Якобы с боксом это эффективнее, чем с боксом.
Converter.ToInt32()
.
Это должно быть, посмотрите последний пример здесь http://msdn.microsoft.com/en-us/library/system.enum.hasflag.aspx