Dela via


Uppräkningstyper (C#-referens)

En uppräkningstyp (eller uppräkningstyp) är en värdetyp som definieras av en uppsättning namngivna konstanter av den underliggande integralens numeriska typ. Om du vill definiera en uppräkningstyp använder du nyckelordet enum och anger namnen på uppräkningsmedlemmar:

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

Som standardinställning är de associerade konstanta värdena för uppräkningsmedlemmar av typen int; de börjar med noll och ökar med ett enligt textordningen i definitionen. Du kan uttryckligen ange andra heltalstyper som en underliggande typ av en uppräkning. Du kan också uttryckligen ange de associerade konstantvärdena, som följande exempel visar:

enum ErrorCode : ushort
{
    None = 0,
    Unknown = 1,
    ConnectionLost = 100,
    OutlierReading = 200
}

Du kan inte definiera en metod i definitionen av en uppräkningstyp. Om du vill lägga till funktioner i en uppräkningstyp skapar du en tilläggsmetod.

Standardvärdet för en uppräkningstyp E är värdet som genereras av uttrycket (E)0, även om noll inte har motsvarande uppräkningsmedlem.

Implicita konverteringar från noll

C# tillåter implicita konverteringar från literalvärdet 0 till valfri uppräkningstyp och från const värden som är lika med noll. Det här beteendet kan leda till oväntade resultat när ett uppräkning inte inkluderar en medlem med värdet noll:

public enum GpioPort
{
    GpioA = 1,
    GpioB,
    GpioC,
    GpioD
}

public class ZeroConversionExample
{
    public static void Main()
    {
        // This compiles without warning but creates an invalid enum value
        GpioPort port1 = (GpioPort)0;
        Console.WriteLine($"port1: {port1}"); // Output: port1: 0

        // This also compiles due to implicit conversion from zero
        GpioPort port2 = GetPort(0);
        Console.WriteLine($"port2: {port2}"); // Output: port2: 0

        // Check if the enum value is valid
        bool isValid1 = Enum.IsDefined(typeof(GpioPort), port1);
        bool isValid2 = Enum.IsDefined(typeof(GpioPort), port2);
        Console.WriteLine($"port1 is valid: {isValid1}"); // Output: port1 is valid: False
        Console.WriteLine($"port2 is valid: {isValid2}"); // Output: port2 is valid: False

        // Safer approach - validate enum values
        if (Enum.IsDefined(typeof(GpioPort), 0))
        {
            GpioPort safePort = (GpioPort)0;
        }
        else
        {
            Console.WriteLine("Value 0 is not a valid GpioPort");
            // Handle the invalid case appropriately
        }
    }

    public static GpioPort GetPort(GpioPort port)
    {
        return port;
    }
}

I föregående exempel tilldelas både port1 och port2 värdet 0, men GpioPort har ingen medlem med det värdet. Metoden Enum.IsDefined bekräftar att dessa är ogiltiga uppräkningsvärden.

Den här implicita konverteringen finns eftersom 0-bitarsmönstret är standard för alla structtyper, inklusive alla uppräkningstyper. Det kan dock introducera buggar i koden. Så här undviker du dessa problem:

  • Du bör nästan alltid definiera en medlem med värdet 0 i dina uppräkningar.
  • Använd Enum.IsDefined för att verifiera uppräkningsvärden när du konverterar från numeriska typer.
  • Var försiktig när du använder numeriska parametrar som implicit kan konverteras till uppräkningstyper.

Du använder en uppräkningstyp för att representera ett val från en uppsättning ömsesidigt uteslutande värden eller en kombination av val. Om du vill representera en kombination av val definierar du en uppräkningstyp som bitflaggor.

Uppräkningstyper som bitflaggor

Om du vill att en uppräkningstyp ska representera en kombination av val definierar du uppräkningsmedlemmar för dessa val, så att ett enskilt val är ett bitfält. Det vill säga att de associerade värdena för dessa uppräkningsmedlemmar bör vara tvåpotenser. Sedan kan du använda de bitvis logiska operatorerna | eller & för att kombinera val eller korsningar av alternativ. Om du vill ange att en uppräkningstyp deklarerar bitfält använder du attributet Flaggor på den. Som följande exempel visar kan du även inkludera några typiska kombinationer i definitionen av en uppräkningstyp.

[Flags]
public enum Days
{
    None      = 0b_0000_0000,  // 0
    Monday    = 0b_0000_0001,  // 1
    Tuesday   = 0b_0000_0010,  // 2
    Wednesday = 0b_0000_0100,  // 4
    Thursday  = 0b_0000_1000,  // 8
    Friday    = 0b_0001_0000,  // 16
    Saturday  = 0b_0010_0000,  // 32
    Sunday    = 0b_0100_0000,  // 64
    Weekend   = Saturday | Sunday
}

public class FlagsEnumExample
{
    public static void Main()
    {
        Days meetingDays = Days.Monday | Days.Wednesday | Days.Friday;
        Console.WriteLine(meetingDays);
        // Output:
        // Monday, Wednesday, Friday

        Days workingFromHomeDays = Days.Thursday | Days.Friday;
        Console.WriteLine($"Join a meeting by phone on {meetingDays & workingFromHomeDays}");
        // Output:
        // Join a meeting by phone on Friday

        bool isMeetingOnTuesday = (meetingDays & Days.Tuesday) == Days.Tuesday;
        Console.WriteLine($"Is there a meeting on Tuesday: {isMeetingOnTuesday}");
        // Output:
        // Is there a meeting on Tuesday: False

        var a = (Days)37;
        Console.WriteLine(a);
        // Output:
        // Monday, Wednesday, Saturday
    }
}

Mer information och exempel finns på System.FlagsAttributeAPI-referenssidan och avsnittet Icke-exklusiva medlemmar och attributet FlaggorSystem.Enum API-referenssidan.

System.Enum-typen och uppräkningsbegränsningen

Typen System.Enum är den abstrakta basklassen för alla uppräkningstyper. Den innehåller ett antal metoder för att hämta information om en uppräkningstyp och dess värden. Mer information och exempel finns på API-referenssidan System.Enum .

Du kan använda System.Enum i en basklassbegränsning (som kallas uppräkningsbegränsningen) för att ange att en typparameter är en uppräkningstyp. Alla uppräkningstyper uppfyller också villkoret struct , som används för att ange att en typparameter är en värdetyp som inte kan nollföras.

Omvandlingar

För alla uppräkningstyper finns det explicita konverteringar mellan uppräkningstypen och dess underliggande integraltyp. Om du omvandlar ett uppräkningsvärde till dess underliggande typ är resultatet det associerade integralvärdet för en uppräkningsmedlem.

public enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

public class EnumConversionExample
{
    public static void Main()
    {
        Season a = Season.Autumn;
        Console.WriteLine($"Integral value of {a} is {(int)a}");  // output: Integral value of Autumn is 2

        var b = (Season)1;
        Console.WriteLine(b);  // output: Summer

        var c = (Season)4;
        Console.WriteLine(c);  // output: 4
    }
}

Enum.IsDefined Använd metoden för att avgöra om en uppräkningstyp innehåller en uppräkningsmedlem med det specifika associerade värdet.

Det finns för varje uppräkningstyp boxnings- och avboxningskonverteringar till och från System.Enum typen.

Språkspecifikation för C#

Mer information finns i följande avsnitt i C#-språkspecifikationen:

Se även