次の方法で共有


列挙型 (C# リファレンス)

列挙型 (または列挙型) は、基になる整数数値型の名前付き定数のセットによって定義される型です。 列挙型を定義するには、 enum キーワードを使用し、 列挙型メンバーの名前を指定します。

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

既定では、列挙型メンバーの関連付けられている定数値は int型です。0 から始まり、定義テキストの順序に従って 1 ずつ増加します。 その他の 整数数値 型は、列挙型の基になる型として明示的に指定できます。 次の例に示すように、関連付けられている定数値を明示的に指定することもできます。

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

列挙型の定義内でメソッドを定義することはできません。 列挙型に機能を追加するには、 拡張メンバーを作成します。

E列挙型の既定値は、0 に対応する列挙型メンバーがない場合でも、式(E)0によって生成される値です。

ゼロからの暗黙的な変換

C# では、リテラル値 0 から任意の列挙型への暗黙的な変換と、0 に等しい値 const 変換できます。 この動作により、列挙型に値が 0 のメンバーが含まれていない場合、予期しない結果が発生する可能性があります。

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

前の例では、 port1port2 の両方に 0値が割り当てられますが、 GpioPort にはその値を持つメンバーがありません。 Enum.IsDefinedメソッドは、これらが無効な列挙値であることを確認します。

この暗黙的な変換が存在するのは、0 ビット パターンが、すべての列挙型を含むすべての構造体型の既定値であるためです。 ただし、コードにバグが発生する可能性があります。 これらの問題を回避する方法:

  • ほとんどの場合、列挙型で値 0 を持つメンバーを定義する必要があります。
  • Enum.IsDefinedを使用して、数値型から変換するときに列挙型の値を検証します。
  • 列挙型に暗黙的に変換される可能性がある数値パラメーターを使用する場合は注意してください。

列挙型を使用して、相互に排他的な値のセットまたは選択肢の組み合わせから選択を表します。 選択肢の組み合わせを表すには、列挙型をビット フラグとして定義します。

ビット フラグとしての列挙型

列挙型で選択肢の組み合わせを表す場合は、個々の選択肢がビット フィールドになるように、それらの選択肢の列挙型メンバーを定義します。 つまり、これらの列挙型メンバーの関連する値は、2 の累乗である必要があります。 次に、 ビットごとの論理演算子 | または & を使用して、選択肢を組み合わせたり、選択肢の組み合わせを交差させたりすることができます。 列挙型がビット フィールドを宣言することを示すには、 Flags 属性を適用します。 次の例に示すように、列挙型の定義に一般的な組み合わせを含めることもできます。

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

詳細と例については、System.FlagsAttribute API リファレンス ページと、 API リファレンス ページのSystem.Enumセクションを参照してください。

System.Enum 型と列挙型定数

System.Enum型は、すべての列挙型の抽象基底クラスです。 列挙型とその値に関する情報を取得するためのメソッドが多数用意されています。 詳細と例については、 System.Enum API リファレンス ページを参照してください。

基底クラス制約 (列挙型制約と呼ばれます) で System.Enum を使用して、型パラメーターが 列挙型であることを指定できます。 列挙型は、 struct 制約も満たします。これは、型パラメーターが null 非許容値型であることを指定するために使用されます。

コンバージョン

列挙型には、列挙型とその基になる整数型の間に明示的な変換が存在します。 列挙型の値を基になる型に キャスト した場合、結果は列挙型メンバーの関連付けられた整数値になります。

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 メソッドを使用して、列挙型に特定の関連付けられた値を持つ列挙型メンバーが含まれているかどうかを判断します。

どの列挙型にも、型との間でSystem.Enum変換が存在します。

C# 言語仕様

詳細については、「C# 言語仕様」の次のセクションを参照してください。

こちらもご覧ください