Sdílet prostřednictvím


Typy výčtu (referenční dokumentace jazyka C#)

Typ výčtu (nebo typ výčtu) je typ hodnoty definovaný sadou pojmenovaných konstant základního celočíselného číselného typu. K definování typu výčtu enum použijte klíčové slovo a zadejte názvy členů výčtu:

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

Ve výchozím nastavení jsou přidružené konstantní hodnoty členů výčtu typu int; začínají nulou a zvyšují se o jednu podle pořadí jejich definice. Jako základní typ výčtu můžete explicitně zadat jakýkoli jiný celočíselný číselný typ. Můžete také explicitně zadat přidružené konstantní hodnoty, jak ukazuje následující příklad:

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

V definici typu výčtu nelze definovat metodu. Pokud chcete přidat funkce do typu výčtu, vytvořte člena rozšíření.

Výchozí hodnota typu E výčtu je hodnota vytvořená výrazem (E)0, i když nula nemá odpovídající člen výčtu.

Implicitní převody z nuly

Jazyk C# umožňuje implicitní převody z literálové hodnoty 0 na libovolný typ výčtu a z const hodnot rovnajících se nule. Toto chování může vést k neočekávaným výsledkům, pokud výčet neobsahuje člena s hodnotou nula:

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;
    }
}

V předchozím příkladu port1 jsou obě a port2 jsou přiřazeny hodnoty 0, ale GpioPort nemá žádný člen s danou hodnotou. Metoda Enum.IsDefined potvrdí, že jsou neplatné hodnoty výčtu.

Tento implicitní převod existuje, protože 0bitový vzor je výchozí pro všechny typy struktur, včetně všech typů výčtu. Může ale do kódu zavádět chyby. Chcete-li se těmto problémům vyhnout:

  • Téměř vždy byste měli definovat člena s hodnotou 0 v výčtech.
  • Slouží Enum.IsDefined k ověření hodnot výčtu při převodu z číselných typů.
  • Při použití číselných parametrů, které mohou být implicitně převedeny na typy výčtů, buďte opatrní.

Typ výčtu slouží k vyjádření výběru ze sady vzájemně se vylučujících hodnot nebo kombinace voleb. Chcete-li reprezentovat kombinaci voleb, definujte typ výčtu jako bitové příznaky.

Výčtové typy jako bitové příznaky

Pokud chcete, aby typ výčtu představoval kombinaci voleb, definujte členy výčtu pro tyto volby tak, aby jednotlivá volba byla bit pole. To znamená, že přidružené hodnoty těchto členů výčtu by měly být mocniny dvou. Poté můžete použít bitové logické operátory | nebo & pro kombinování voleb nebo propojení kombinací voleb. Chcete-li označit, že typ výčtu deklaruje bitová pole, použijte na něj atribut Flags . Jak ukazuje následující příklad, můžete také zahrnout některé typické kombinace v definici typu výčtu.

[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
    }
}

Další informace a příklady najdete na System.FlagsAttribute stránce s referenčními informacemi k rozhraní API a v části nevýluční členové a atribut Flags na System.Enum stránce referenčních informací k rozhraní API.

Typ System.Enum a omezení typu výčtu

Typ System.Enum je abstraktní základní třída všech typů výčtu. Poskytuje řadu metod pro získání informací o typu výčtu a jejích hodnotách. Další informace a příklady najdete na System.Enum referenční stránce rozhraní API.

V omezení základní třídy (označované jako System.Enum) můžete určit, že parametr typu je typ výčtu. Jakýkoli typ výčtu struct také splňuje omezení, které se používá k určení, že parametr typu je nenulový typ hodnoty.

Převody

Pro jakýkoli typ výčtu existují explicitní převody mezi typem výčtu a jeho základním celočíselným typem. Pokud přetypujete hodnotu výčtu na její základní typ, výsledkem je přidružená celočíselná hodnota člena výčtu.

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 Pomocí metody určete, zda typ výčtu obsahuje člen výčtu s určitou přidruženou hodnotou.

Pro jakýkoli typ výčtu existují převody zapouzdření a rozbalení do daného typu a zpět.

Specifikace jazyka C#

Další informace najdete v následujících částech specifikace jazyka C#:

Viz také