Должен "или" работать с.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

Другие вопросы по тегам