Что действительно делает атрибут [Флаги]?

Что действительно делает [Flags]?

Я знаю, что он изменяет поведение Enum.ToString, но делает ли он что-нибудь еще? (например, разное поведение компилятора или режима работы и т.д.)


Изменить. Да, я знаю, что он документирует тот факт, что перечисление предназначено для использования в качестве поразрядных флагов и более логично применять его к битовым флагам. Я спрашивал больше о конкретных изменениях поведения, но не об общем программировании.

Ответ 1

Из статьи MSDN:

Интересно отметить, что когда Указаны флаги, Parse и Format методы имеют расширенные возможности.

Аналогично, метод Parse может успешно разобрать запятую строка, как показано в правильное числовое значение.

Ответ 2

Смотрите сообщение Дэвида М. Кина здесь. Это, по-видимому, проблема языкового взаимодействия:

Несмотря на то, что С# с радостью позволяет пользователям выполнять операции с битами по перечислениям без FlagsAttribute, Visual Basic этого не делает. Поэтому, если вы подвергаете типы другим языкам, то отличная переписка с FlagsAttribute - хорошая идея; он также дает понять, что члены перечисления предназначены для совместного использования.

Привет

Дэвид

Ответ 3

Вот список конкретных поведенческих различий:

  • Установка перечисления с [flags] в None очищает все флаги.
  • Метод HasFlags работает только тогда, когда этот атрибут присутствует.
  • Как сказал Девио, он меняет возможности методов Parse и Format. Он связан с этой статьей. По-видимому, это также влияет на то, что показано в Debuggers.
  • Я думал, что [флаги], вероятно, повлияли на формирование кода в webservices, но кажется, что это не так.
  • Чтобы быть ясным, побитовые операции разрешены при любом перечислении, с или без [flags]. Но использование этого - лучшая практика.

Подробнее: http://msdn.microsoft.com/en-us/library/ms229062.aspx

Ответ 4

Если вы спросите, что он делает под капотом, насколько я знаю, он меняет метод ToString(), ничего другого.

В .Net 4 у вас есть HasFlags - метод для проверки определенных флагов. Если я правильно интерпретирую msdn, вы должны использовать атрибут flags для использования этого метода. Но я не пробовал.

Ответ 5

На практике одно из применений, которое я использую, указывает на несколько статусов. Это упрощение кода, который оценивает результаты тестирования. Тест может быть "Хорошо", или у него может быть несколько причин не быть "Хорошо". Преимущество, которое это дает, заключается в том, что у меня есть один метод, который оценивает тесты "Ok-ness", и этот метод способен указать все возможные условия отказа с одним возвратом. Может быть, не лучший дизайн, но он работает в этом случае.

[Flags]
public enum ResultStatusEnum
{
    Ok = 0x1,
    SampleInvalid = 0x2,
    DirectionInvalid = 0x4,
    TestIsNotValid = 0x8
}

Вы устанавливаете его так:

ResultStatusEnum res = ResultStatusEnum.SampleInvalid | ResultStatusEnum.DirectionInvalid;

Недостатком является то, что проверка значений перечисления становится громоздкой. Это не будет (обязательно) работать:

res == ResultStatusEnum.Ok

Вы должны сделать это, чтобы проверить:

ResultStatusEnum.SampleInvalid == (res & ResultStatusEnum.SampleInvalid)

В этом случае нелогично иметь ResultStatusEnum.Ok & ResultStatusEnum.SampleInvalid, но я просто убеждаюсь, что это не тот случай, когда я использую перечисление.