Sdílet prostřednictvím


System.FlagsAttribute – třída

Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.

Atribut FlagsAttribute označuje, že výčet může být považován za bitové pole. To znamená sada příznaků.

Bitová pole se obecně používají pro seznamy prvků, které mohou nastat v kombinaci, zatímco výčtové konstanty se obvykle používají pro seznamy vzájemně se vylučujících prvků. Bitová pole jsou proto navržena tak, aby byla kombinována s bitovým OR provozem pro generování nepojmenovaných hodnot, zatímco výčtové konstanty nejsou. Jazyky se liší v jejich používání bitových polí v porovnání s výčtovými konstantami.

Atributy FlagsAttribute

AttributeUsageAttribute je použit pro tuto třídu a jeho Inherited vlastnost určuje false. Tento atribut lze použít pouze u výčtů.

Pokyny pro FlagsAttribute a výčet

  • FlagsAttribute Vlastní atribut použijte pro výčet pouze v případě, že je pro číselnou hodnotu provedena bitové operace (AND, OR, EXCLUSIVE OR).

  • Definujte konstanty výčtu v mocninách dvou, tj. 1, 2, 4, 8 atd. To znamená, že jednotlivé příznaky v kombinovaných výčtových konstantách se nepřekrývají.

  • Zvažte vytvoření výčtové konstanty pro běžně používané kombinace příznaků. Pokud máte například výčet používaný pro vstupně-výstupní operace souboru, které obsahují výčtové konstanty Read = 1 , a Write = 2zvažte vytvoření výčtové konstanty ReadWrite = Read OR Write, která kombinuje Read a Write příznaky. Kromě toho může být bitové operace OR použitá ke kombinování příznaků v některých případech považována za pokročilý koncept, který by neměl být vyžadován pro jednoduché úlohy.

  • Pokud definujete záporné číslo jako konstantu s výčtem příznaku, protože mnoho pozic příznaků může být nastaveno na hodnotu 1, což může kód matoucí a podpořit chyby kódování.

  • Pohodlný způsob, jak otestovat, zda je příznak nastaven v číselné hodnotě, je provést bitovou operaci AND mezi číselnou hodnotou a příznakem výčtu konstanty, která nastaví všechny bity v číselné hodnotě na nulu, která neodpovídá příznaku, a pak otestujte, zda výsledek této operace je roven výčtu příznaku konstanty.

  • Slouží None jako název výčtové konstanty příznaku, jejíž hodnota je nula. Výčtovou konstantu None v bitové operaci AND nelze použít k otestování příznaku, protože výsledek je vždy nula. Můžete ale provést logickou, nikoli bitovou porovnávání číselné hodnoty a None výčtové konstanty, abyste zjistili, jestli jsou některé bity v číselné hodnotě nastaveny.

    Pokud místo výčtu příznaků vytvoříte výčet hodnot, je stále vhodné vytvořit výčtovou konstantu None . Důvodem je to, že ve výchozím nastavení je paměť používaná pro výčet inicializována na nulu modulem CLR (Common Language Runtime). Pokud tedy nedefinujete konstantu, jejíž hodnota je nula, bude výčet při vytváření obsahovat neplatnou hodnotu.

    Pokud existuje jasný výchozí případ, který vaše aplikace potřebuje reprezentovat, zvažte použití výčtové konstanty, jejíž hodnota je nula, aby představovala výchozí hodnotu. Pokud neexistuje žádný výchozí případ, zvažte použití výčtové konstanty, jejíž hodnota je nula, což znamená, že případ, který není reprezentován žádnou z ostatních výčtových konstant.

  • Nedefinujte hodnotu výčtu výhradně pro zrcadlení stavu samotné výčtu. Například nedefinujte výčtovou konstantu, která pouze označuje konec výčtu. Pokud potřebujete určit poslední hodnotu výčtu, zkontrolujte tuto hodnotu explicitně. Kromě toho můžete provést kontrolu rozsahu první a poslední výčtové konstanty, pokud jsou všechny hodnoty v rozsahu platné.

  • Nezadávejte výčtové konstanty, které jsou vyhrazeny pro budoucí použití.

  • Při definování metody nebo vlastnosti, která přebírá výčtovou konstantu jako hodnotu, zvažte ověření hodnoty. Důvodem je, že číselnou hodnotu můžete přetypovat na typ výčtu, i když tato číselná hodnota není definována ve výčtu.

Příklady

Následující příklad znázorňuje použití atributu FlagsAttribute a ukazuje účinek na ToString metodu použití FlagsAttribute na Enum deklaraci.

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

Předchozí příklad definuje dva výčty SingleHue související s barvou a MultiHue. Druhý atribut má FlagsAttribute ; první atribut neobsahuje. Příklad ukazuje rozdíl v chování v případě, že rozsah celých čísel, včetně celých čísel, které nepředstavují podkladové hodnoty typu výčtu, jsou přetypovány na typ výčtu a jejich řetězcové reprezentace zobrazené. Všimněte si například, že 3 nelze reprezentovat jako SingleHue hodnotu, protože 3 není podkladovou hodnotou žádného SingleHue člena, zatímco FlagsAttribute atribut umožňuje reprezentovat hodnotu 3 jako MultiHue hodnotu Black, Red.

Následující příklad definuje další výčet s atributem FlagsAttribute a ukazuje, jak používat bitové logické operátory a operátory rovnosti k určení, zda jsou v hodnotě výčtu nastavena jedna nebo více bitových polí. Můžete k tomu také použít metodu Enum.HasFlag , která se ale v tomto příkladu nezobrazuje.

using System;

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

public class Example1
{
    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 Example1
   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