FlagsAttribute Класс

Определение

Указывает, что перечисление может обрабатываться как битовое поле (т. е. набор флагов).

public ref class FlagsAttribute : Attribute
[System.AttributeUsage(System.AttributeTargets.Enum, Inherited=false)]
public class FlagsAttribute : Attribute
[System.AttributeUsage(System.AttributeTargets.Enum, Inherited=false)]
[System.Serializable]
public class FlagsAttribute : Attribute
[System.AttributeUsage(System.AttributeTargets.Enum, Inherited=false)]
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class FlagsAttribute : Attribute
[<System.AttributeUsage(System.AttributeTargets.Enum, Inherited=false)>]
type FlagsAttribute = class
    inherit Attribute
[<System.AttributeUsage(System.AttributeTargets.Enum, Inherited=false)>]
[<System.Serializable>]
type FlagsAttribute = class
    inherit Attribute
[<System.AttributeUsage(System.AttributeTargets.Enum, Inherited=false)>]
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type FlagsAttribute = class
    inherit Attribute
Public Class FlagsAttribute
Inherits Attribute
Наследование
FlagsAttribute
Атрибуты

Примеры

В следующем примере показано использование атрибута FlagsAttribute и показывается влияние на ToString метод использования FlagsAttribute в объявлении Enum .

using namespace System;

// Define an Enum without FlagsAttribute.
public enum class SingleHue : short
{
   None = 0,
   Black = 1,
   Red = 2,
   Green = 4,
   Blue = 8
};

// Define an Enum with FlagsAttribute.
[Flags]
enum class MultiHue : short
{
   None = 0,
   Black = 1,
   Red = 2,
   Green = 4,
   Blue = 8
};

int main()
{
   // Display all possible combinations of values.
   Console::WriteLine(
        "All possible combinations of values without FlagsAttribute:");
   for (int val = 0; val <= 16; val++)
      Console::WriteLine("{0,3} - {1:G}", val, (SingleHue)val);
      
   Console::WriteLine(
        "\nAll possible combinations of values with FlagsAttribute:");
   
   // Display all combinations of values, and invalid values.
   for (int val = 0; val <= 16; val++ )
      Console::WriteLine("{0,3} - {1:G}", val, (MultiHue)val);
}
// The example displays the following output:
//       All possible combinations of values without FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - 3
//         4 - Green
//         5 - 5
//         6 - 6
//         7 - 7
//         8 - Blue
//         9 - 9
//        10 - 10
//        11 - 11
//        12 - 12
//        13 - 13
//        14 - 14
//        15 - 15
//        16 - 16
//       
//       All possible combinations of values with FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - Black, Red
//         4 - Green
//         5 - Black, Green
//         6 - Red, Green
//         7 - Black, Red, Green
//         8 - Blue
//         9 - Black, Blue
//        10 - Red, Blue
//        11 - Black, Red, Blue
//        12 - Green, Blue
//        13 - Black, Green, Blue
//        14 - Red, Green, Blue
//        15 - Black, Red, Green, Blue
//        16 - 16
using System;

class Example
{
   // Define an Enum without FlagsAttribute.
   enum SingleHue : short
   {
      None = 0,
      Black = 1,
      Red = 2,
      Green = 4,
      Blue = 8
   };

   // Define an Enum with FlagsAttribute.
   [Flags]
   enum MultiHue : short
   {
      None = 0,
      Black = 1,
      Red = 2,
      Green = 4,
      Blue = 8
   };

   static void Main( )
   {
      // Display all possible combinations of values.
      Console.WriteLine(
           "All possible combinations of values without FlagsAttribute:");
      for(int val = 0; val <= 16; val++ )
         Console.WriteLine( "{0,3} - {1:G}", val, (SingleHue)val);

      // Display all combinations of values, and invalid values.
      Console.WriteLine(
           "\nAll possible combinations of values with FlagsAttribute:");
      for( int val = 0; val <= 16; val++ )
         Console.WriteLine( "{0,3} - {1:G}", val, (MultiHue)val);
   }
}
// The example displays the following output:
//       All possible combinations of values without FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - 3
//         4 - Green
//         5 - 5
//         6 - 6
//         7 - 7
//         8 - Blue
//         9 - 9
//        10 - 10
//        11 - 11
//        12 - 12
//        13 - 13
//        14 - 14
//        15 - 15
//        16 - 16
//
//       All possible combinations of values with FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - Black, Red
//         4 - Green
//         5 - Black, Green
//         6 - Red, Green
//         7 - Black, Red, Green
//         8 - Blue
//         9 - Black, Blue
//        10 - Red, Blue
//        11 - Black, Red, Blue
//        12 - Green, Blue
//        13 - Black, Green, Blue
//        14 - Red, Green, Blue
//        15 - Black, Red, Green, Blue
//        16 - 16
open System

// Define an Enum without FlagsAttribute.
type SingleHue =
    | None = 0
    | Black = 1
    | Red = 2
    | Green = 4
    | Blue = 8

// Define an Enum with FlagsAttribute.
[<Flags>]
type MultiHue =
    | None = 0
    | Black = 1
    | Red = 2
    | Green = 4
    | Blue = 8

// Display all possible combinations of values.
printfn "All possible combinations of values without FlagsAttribute:"
for i = 0 to 16 do
    printfn $"{i,3} - {enum<SingleHue> i:G}"

// Display all combinations of values, and invalid values.
printfn "\nAll possible combinations of values with FlagsAttribute:"
for i = 0 to 16 do
    printfn $"{i,3} - {enum<MultiHue> i:G}"

// The example displays the following output:
//       All possible combinations of values without FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - 3
//         4 - Green
//         5 - 5
//         6 - 6
//         7 - 7
//         8 - Blue
//         9 - 9
//        10 - 10
//        11 - 11
//        12 - 12
//        13 - 13
//        14 - 14
//        15 - 15
//        16 - 16
//
//       All possible combinations of values with FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - Black, Red
//         4 - Green
//         5 - Black, Green
//         6 - Red, Green
//         7 - Black, Red, Green
//         8 - Blue
//         9 - Black, Blue
//        10 - Red, Blue
//        11 - Black, Red, Blue
//        12 - Green, Blue
//        13 - Black, Green, Blue
//        14 - Red, Green, Blue
//        15 - Black, Red, Green, Blue
//        16 - 16
Module Example
   ' Define an Enum without FlagsAttribute.
   Enum SingleHue As Short
      None = 0
      Black = 1
      Red = 2
      Green = 4
      Blue = 8
   End Enum

   ' Define an Enum with FlagsAttribute.
   <Flags()> 
   Enum MultiHue As Short
      None = 0
      Black = 1
      Red = 2
      Green = 4
      Blue = 8
   End Enum

   Sub Main()
      ' Display all possible combinations of values.
      Console.WriteLine(
           "All possible combinations of values without FlagsAttribute:")
      For val As Integer = 0 To 16
         Console.WriteLine("{0,3} - {1:G}", val, CType(val, SingleHue))
     Next 
     Console.WriteLine()
     
     ' Display all combinations of values, and invalid values.
     Console.WriteLine( 
          "All possible combinations of values with FlagsAttribute:")
     For val As Integer = 0 To 16
        Console.WriteLine( "{0,3} - {1:G}", val, CType(val, MultiHue))
     Next 
   End Sub 
End Module 
' The example displays the following output:
'       All possible combinations of values without FlagsAttribute:
'         0 - None
'         1 - Black
'         2 - Red
'         3 - 3
'         4 - Green
'         5 - 5
'         6 - 6
'         7 - 7
'         8 - Blue
'         9 - 9
'        10 - 10
'        11 - 11
'        12 - 12
'        13 - 13
'        14 - 14
'        15 - 15
'        16 - 16
'       
'       All possible combinations of values with FlagsAttribute:
'         0 - None
'         1 - Black
'         2 - Red
'         3 - Black, Red
'         4 - Green
'         5 - Black, Green
'         6 - Red, Green
'         7 - Black, Red, Green
'         8 - Blue
'         9 - Black, Blue
'        10 - Red, Blue
'        11 - Black, Red, Blue
'        12 - Green, Blue
'        13 - Black, Green, Blue
'        14 - Red, Green, Blue
'        15 - Black, Red, Green, Blue
'        16 - 16

В предыдущем примере определяются два перечисления, связанные с цветом, SingleHue и MultiHue. Последний имеет FlagsAttribute атрибут; первый — нет. В примере показано различие в поведении, когда диапазон целых чисел, включая целые числа, которые не представляют базовые значения типа перечисления, приводятся к типу перечисления и их строковым представлениям. Например, обратите внимание, что 3 не может быть представлено SingleHue как значение, так как 3 не является базовым значением любого SingleHue члена, тогда как FlagsAttribute атрибут позволяет представить 3 как MultiHue значение Black, Red.

В следующем примере определяется другой перечисление с атрибутом FlagsAttribute и показано, как использовать побитовые логические операторы и операторы равенства, чтобы определить, задано ли одно или несколько битовых полей в значении перечисления. Этот метод также можно использовать Enum.HasFlag для этого, но это не показано в этом примере.

using namespace System;

[Flags]
enum class PhoneService
{
   None = 0,
   LandLine = 1,
   Cell = 2,
   Fax = 4,
   Internet = 8,
   Other = 16
};

void main()
{
   // Define three variables representing the types of phone service
   // in three households.
   PhoneService household1 = PhoneService::LandLine | PhoneService::Cell |
                             PhoneService::Internet;
   PhoneService household2 = PhoneService::None;
   PhoneService household3 = PhoneService::Cell | PhoneService::Internet;

   // Store the variables in an array for ease of access.
   array<PhoneService>^ households = { household1, household2, household3 };

   // Which households have no service?
   for (int ctr = 0; ctr < households->Length; ctr++)
      Console::WriteLine("Household {0} has phone service: {1}",
                         ctr + 1,
                         households[ctr] == PhoneService::None ?
                             "No" : "Yes");
   Console::WriteLine();

   // Which households have cell phone service?
   for (int ctr = 0; ctr < households->Length; ctr++)
      Console::WriteLine("Household {0} has cell phone service: {1}",
                         ctr + 1,
                         (households[ctr] & PhoneService::Cell) == PhoneService::Cell ?
                            "Yes" : "No");
   Console::WriteLine();

   // Which households have cell phones and land lines?
   PhoneService cellAndLand = PhoneService::Cell | PhoneService::LandLine;
   for (int ctr = 0; ctr < households->Length; ctr++)
      Console::WriteLine("Household {0} has cell and land line service: {1}",
                         ctr + 1,
                         (households[ctr] & cellAndLand) == cellAndLand ?
                            "Yes" : "No");
   Console::WriteLine();

   // List all types of service of each household?//
   for (int ctr = 0; ctr < households->Length; ctr++)
      Console::WriteLine("Household {0} has: {1:G}",
                         ctr + 1, households[ctr]);
   Console::WriteLine();
}
// The example displays the following output:
//    Household 1 has phone service: Yes
//    Household 2 has phone service: No
//    Household 3 has phone service: Yes
//
//    Household 1 has cell phone service: Yes
//    Household 2 has cell phone service: No
//    Household 3 has cell phone service: Yes
//
//    Household 1 has cell and land line service: Yes
//    Household 2 has cell and land line service: No
//    Household 3 has cell and land line service: No
//
//    Household 1 has: LandLine, Cell, Internet
//    Household 2 has: None
//    Household 3 has: Cell, Internet
using System;

[Flags]
public enum PhoneService
{
   None = 0,
   LandLine = 1,
   Cell = 2,
   Fax = 4,
   Internet = 8,
   Other = 16
}

public class Example
{
   public static void Main()
   {
      // Define three variables representing the types of phone service
      // in three households.
      var household1 = PhoneService.LandLine | PhoneService.Cell |
                       PhoneService.Internet;
      var household2 = PhoneService.None;
      var household3 = PhoneService.Cell | PhoneService.Internet;

      // Store the variables in an array for ease of access.
      PhoneService[] households = { household1, household2, household3 };

      // Which households have no service?
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has phone service: {1}",
                           ctr + 1,
                           households[ctr] == PhoneService.None ?
                               "No" : "Yes");
      Console.WriteLine();

      // Which households have cell phone service?
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has cell phone service: {1}",
                           ctr + 1,
                           (households[ctr] & PhoneService.Cell) == PhoneService.Cell ?
                              "Yes" : "No");
      Console.WriteLine();

      // Which households have cell phones and land lines?
      var cellAndLand = PhoneService.Cell | PhoneService.LandLine;
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has cell and land line service: {1}",
                           ctr + 1,
                           (households[ctr] & cellAndLand) == cellAndLand ?
                              "Yes" : "No");
      Console.WriteLine();

      // List all types of service of each household?//
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has: {1:G}",
                           ctr + 1, households[ctr]);
      Console.WriteLine();
   }
}
// The example displays the following output:
//    Household 1 has phone service: Yes
//    Household 2 has phone service: No
//    Household 3 has phone service: Yes
//
//    Household 1 has cell phone service: Yes
//    Household 2 has cell phone service: No
//    Household 3 has cell phone service: Yes
//
//    Household 1 has cell and land line service: Yes
//    Household 2 has cell and land line service: No
//    Household 3 has cell and land line service: No
//
//    Household 1 has: LandLine, Cell, Internet
//    Household 2 has: None
//    Household 3 has: Cell, Internet
open System

[<Flags>]
type PhoneService =
    | None = 0
    | LandLine = 1
    | Cell = 2
    | Fax = 4
    | Internet = 8
    | Other = 16

// Define three variables representing the types of phone service
// in three households.
let household1 = 
    PhoneService.LandLine ||| PhoneService.Cell ||| PhoneService.Internet

let household2 = 
    PhoneService.None

let household3 = 
    PhoneService.Cell ||| PhoneService.Internet

// Store the variables in a list for ease of access.
let households =
    [ household1; household2; household3 ]

// Which households have no service?
for i = 0 to households.Length - 1 do
    printfn $"""Household {i + 1} has phone service: {if households[i] = PhoneService.None then "No" else "Yes"}"""
printfn ""

// Which households have cell phone service?
for i = 0 to households.Length - 1 do
    printfn $"""Household {i + 1} has cell phone service: {if households[i] &&& PhoneService.Cell = PhoneService.Cell then "Yes" else "No"}"""
printfn ""

// Which households have cell phones and land lines?
let cellAndLand = 
    PhoneService.Cell ||| PhoneService.LandLine

for i = 0 to households.Length - 1 do
    printfn $"""Household {i + 1} has cell and land line service: {if households[i] &&& cellAndLand = cellAndLand then "Yes" else "No"}"""
printfn ""

// List all types of service of each household?//
for i = 0 to households.Length - 1 do
    printfn $"Household {i + 1} has: {households[i]:G}"

// The example displays the following output:
//    Household 1 has phone service: Yes
//    Household 2 has phone service: No
//    Household 3 has phone service: Yes
//
//    Household 1 has cell phone service: Yes
//    Household 2 has cell phone service: No
//    Household 3 has cell phone service: Yes
//
//    Household 1 has cell and land line service: Yes
//    Household 2 has cell and land line service: No
//    Household 3 has cell and land line service: No
//
//    Household 1 has: LandLine, Cell, Internet
//    Household 2 has: None
//    Household 3 has: Cell, Internet
<Flags()>
Public Enum PhoneService As Integer
   None = 0
   LandLine = 1
   Cell = 2
   Fax = 4
   Internet = 8
   Other = 16
End Enum

Module Example
   Public Sub Main()
      ' Define three variables representing the types of phone service
      ' in three households.
      Dim household1 As PhoneService = PhoneService.LandLine Or
                                       PhoneService.Cell Or
                                       PhoneService.Internet
      Dim household2 As PhoneService = PhoneService.None
      Dim household3 As PhoneService = PhoneService.Cell Or
                                       PhoneService.Internet

      ' Store the variables in an array for ease of access.
      Dim households() As PhoneService = { household1, household2,
                                           household3 }

      ' Which households have no service?
      For ctr As Integer = 0 To households.Length - 1
         Console.WriteLine("Household {0} has phone service: {1}",
                           ctr + 1,
                           If(households(ctr) = PhoneService.None,
                              "No", "Yes"))
      Next
      Console.WriteLine()
      
      ' Which households have cell phone service?
      For ctr As Integer = 0 To households.Length - 1
         Console.WriteLine("Household {0} has cell phone service: {1}",
                           ctr + 1,
                           If((households(ctr) And PhoneService.Cell) = PhoneService.Cell,
                              "Yes", "No"))
      Next
      Console.WriteLine()
      
      ' Which households have cell phones and land lines?
      Dim cellAndLand As PhoneService = PhoneService.Cell Or PhoneService.LandLine
      For ctr As Integer = 0 To households.Length - 1
         Console.WriteLine("Household {0} has cell and land line service: {1}",
                           ctr + 1,
                           If((households(ctr) And cellAndLand) = cellAndLand,
                              "Yes", "No"))
      Next
      Console.WriteLine()
      
      ' List all types of service of each household?'
      For ctr As Integer = 0 To households.Length - 1
         Console.WriteLine("Household {0} has: {1:G}",
                           ctr + 1, households(ctr))
      Next
      Console.WriteLine()
   End Sub
End Module
' The example displays the following output:
'    Household 1 has phone service: Yes
'    Household 2 has phone service: No
'    Household 3 has phone service: Yes
'
'    Household 1 has cell phone service: Yes
'    Household 2 has cell phone service: No
'    Household 3 has cell phone service: Yes
'
'    Household 1 has cell and land line service: Yes
'    Household 2 has cell and land line service: No
'    Household 3 has cell and land line service: No
'
'    Household 1 has: LandLine, Cell, Internet
'    Household 2 has: None
'    Household 3 has: Cell, Internet

Комментарии

Битовые поля обычно используются для списков элементов, которые могут встречаться в сочетании, тогда как константы перечисления обычно используются для списков взаимоисключающих элементов. Таким образом, битовые поля предназначены для объединения с побитовой операцией OR для создания неименованных значений, в то время как перечисляемые константы не являются. Языки зависят от их использования битовых полей по сравнению с константами перечисления.

Атрибуты FlagsAttribute

AttributeUsageAttribute применяется к этому классу, а его Inherited свойство указывает false. Этот атрибут можно применять только к перечислениям.

Рекомендации по FlagsAttribute и перечислению

  • Используйте настраиваемый FlagsAttribute атрибут для перечисления только в том случае, если необходимо выполнить побитовую операцию (AND, OR, EXCLUSIVE OR) с числовым значением.

  • Определите константы перечисления в двух силах, то есть 1, 2, 4, 8 и т. д. Это означает, что отдельные флаги в объединенных констант перечислениях не перекрываются.

  • Рассмотрите возможность создания перечислимой константы для часто используемых сочетаний флагов. Например, если у вас есть перечисление, используемое для операций ввода-вывода файлов, содержащих перечисляемые константы Read = 1 , и Write = 2рассмотрите возможность создания перечислимой константы ReadWrite = Read OR Write, которая объединяет Read и Write флаги. Кроме того, побитовая операция OR, используемая для объединения флагов, может считаться расширенной концепцией в некоторых обстоятельствах, которые не должны требоваться для простых задач.

  • Используйте осторожность, если вы определяете отрицательное число в виде перечисляемой константы, так как многие позиции флагов могут иметь значение 1, что может привести к путанице кода и побудить ошибки кодирования.

  • Удобный способ проверить, установлен ли флаг в числовом значении, заключается в выполнении побитовой операции AND между числовым значением и перечисленной константой флага, которая устанавливает все биты в числовом значении равным нулю, которые не соответствуют флагу, а затем проверить, равен ли результат этой операции перечисленной константе.

  • Используйте None в качестве имени перечисляемой константы, значение которой равно нулю. Перечислимую None константу нельзя использовать в побитовой операции AND для проверки флага, так как результат всегда равен нулю. Однако можно выполнить логическое, а не побитовое, сравнение между числовым значением и None перечислимой константой, чтобы определить, заданы ли какие-либо биты в числовом значении.

    При создании перечисления значений вместо перечисления флагов рекомендуется создать перечислимую константу None . Причина заключается в том, что по умолчанию память, используемая для перечисления, инициализируется до нуля средой CLR. Следовательно, если не определить константу, значение которой равно нулю, перечисление будет содержать недопустимое значение при его создании.

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

  • Не определяйте значение перечисления исключительно для зеркального отображения состояния самого перечисления. Например, не определяйте перечисляемую константу, которая просто помечает конец перечисления. Если необходимо определить последнее значение перечисления, проверьте это значение явным образом. Кроме того, можно выполнить проверку диапазона для первой и последней перечисляемой константы, если все значения в диапазоне допустимы.

  • Не указывайте перечисляемые константы, зарезервированные для дальнейшего использования.

  • При определении метода или свойства, который принимает перечислимую константу в качестве значения, рассмотрите возможность проверки значения. Причина заключается в том, что можно привести числовое значение к типу перечисления, даже если это числовое значение не определено в перечислении.

Конструкторы

FlagsAttribute()

Инициализирует новый экземпляр класса FlagsAttribute.

Свойства

TypeId

В случае реализации в производном классе возвращает уникальный идентификатор для этого атрибута Attribute.

(Унаследовано от Attribute)

Методы

Equals(Object)

Возвращает значение, показывающее, равен ли экземпляр указанному объекту.

(Унаследовано от Attribute)
GetHashCode()

Возвращает хэш-код данного экземпляра.

(Унаследовано от Attribute)
GetType()

Возвращает объект Type для текущего экземпляра.

(Унаследовано от Object)
IsDefaultAttribute()

При переопределении в производном классе указывает, является ли значение этого экземпляра значением по умолчанию для производного класса.

(Унаследовано от Attribute)
Match(Object)

При переопределении в производном классе возвращает значение, указывающее, является ли этот экземпляр равным заданному объекту.

(Унаследовано от Attribute)
MemberwiseClone()

Создает неполную копию текущего объекта Object.

(Унаследовано от Object)
ToString()

Возвращает строку, представляющую текущий объект.

(Унаследовано от Object)

Явные реализации интерфейса

_Attribute.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr)

Сопоставляет набор имен соответствующему набору идентификаторов диспетчеризации.

(Унаследовано от Attribute)
_Attribute.GetTypeInfo(UInt32, UInt32, IntPtr)

Возвращает сведения о типе объекта, которые можно использовать для получения сведений о типе интерфейса.

(Унаследовано от Attribute)
_Attribute.GetTypeInfoCount(UInt32)

Возвращает количество предоставляемых объектом интерфейсов для доступа к сведениям о типе (0 или 1).

(Унаследовано от Attribute)
_Attribute.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr)

Предоставляет доступ к открытым свойствам и методам объекта.

(Унаследовано от Attribute)

Применяется к