列挙型 (Enumerated type)

構文

enum MyEnum { A, B, C }

CLRでは、すべての列挙型はSystem.Enumから派生したクラスです。Enum メンバ (System) | MSDN

基礎となる型

すべての列挙型には基礎となる型があり、これは

enum MyEnum : byte {}

のように列挙型の定義時に指定できます。これに指定できる型は下表に示す単純型のみで、省略した場合にはintが採用されます。

符号あり 符号なし
sbyte byte
short ushort
int uint
long ulong

すでに定義されている列挙型の型は、EnumクラスのGetUnderlyingType()メソッドで取得できます。

ビットフラグ

すべての識別子にビットに対応する値を設定することで、列挙型をビットフラグとして利用できます。これはSystem.FlagsAttribute属性として指定することで定義でき、たとえばFileAttributesでは次のように用いられています。

[Serializable]
[Flags]
[System.Runtime.InteropServices.ComVisible(true)]
public enum FileAttributes
{
    // From WinNT.h (FILE_ATTRIBUTE_XXX)
    ReadOnly = 0x1,
    Hidden = 0x2,
    System = 0x4,
    ︙
FileAttributes - fileattributes.cs

このように定義された列挙型は、次のように利用できます。

// 複数のフラグを設定する
FileAttributes a = FileAttributes.ReadOnly | FileAttributes.Hidden;

// フラグの有無を確認する
if ((a & FileAttributes.Hidden) == FileAttributes.Hidden)
{
}

なお.NET Framework 4.0以降ならば、フラグの有無はHasFlag()でも確認できます。Enum.HasFlag(Enum) メソッド (System) | Microsoft Learn

if (a.HasFlag(FileAttributes.Hidden))
{
    // Hiddenがある
}
if (a.HasFlag(FileAttributes.ReadOnly | FileAttributes.Hidden))
{
    // ReadOnlytとHiddenがある
}
if (a.HasFlag(FileAttributes.ReadOnly) || a.HasFlag(FileAttributes.Hidden))
{
    // ReadOnlytまたはHiddenがある
}

// 次のようにも記述できる
if ((a & (FileAttributes.ReadOnly | FileAttributes.Hidden)) != 0)
{
}

このメソッドはFlagsAttributeが付けられた列挙型のビットフィールドを判定するためのものであり、この属性がなければEquals()またはCompareTo()を呼びます。

型の変換

基礎となる型との変換

enum MyEnum1 { A, B, C }
enum MyEnum2 { A, B = 20, C }

public class MyClass
{
    public void Method()
    {
        // 列挙型から、基礎となる型への変換
        int a1 = (int)MyEnum1.A; // 0
        int a2 = (int)MyEnum1.B; // 1
        int a3 = (int)MyEnum1.C; // 2

        int a4 = (int)MyEnum2.A; // 0
        int a5 = (int)MyEnum2.B; // 20
        int a6 = (int)MyEnum2.C; // 21

        // 基礎となる型から、列挙型への変換
        MyEnum1 e1 = (MyEnum1)1; // B
        MyEnum1 e2 = (MyEnum1)3; // 3 (未定義の値)

        MyEnum1 e3 = (MyEnum1)Enum.ToObject(typeof(MyEnum1), 1); // B
        MyEnum1 e4 = (MyEnum1)Enum.ToObject(typeof(MyEnum1), 3); // 3 (未定義の値)
    }
}
変換の実行 - Enum クラス (System) | Microsoft Learn

未定義の値でも列挙型へキャストできるため、予期せぬ値になることがあります。それが問題となるときには、IsDefined()で確認します。Enum.IsDefined メソッド (System) | Microsoft Learn

bool b1 = Enum.IsDefined(typeof(MyEnum1), 1); // true
bool b2 = Enum.IsDefined(typeof(MyEnum1), 3); // false

文字列との変換

列挙型から文字列への変換

enum MyEnum1 { A, B, C }
enum MyEnum2 { A, B = 20, C }

public class MyClass
{
    public void Method()
    {
        string str1 = MyEnum1.B.ToString(); // B
        string str2 = MyEnum2.B.ToString(); // B
    }
}

文字列から列挙型への変換

列挙値の解析 - Enum クラス (System) | MSDN

[ComVisibleAttribute(true)]
public static object Parse(
    Type enumType,
    string value
)
Enum.Parse メソッド (Type, String) (System) | MSDN

このメソッドでは大文字/小文字が区別されて評価されます。その区別が不要ならば、次のメソッドでignoreCaseをtrueとします。

[ComVisibleAttribute(true)]
public static object Parse(
    Type enumType,
    string value,
    bool ignoreCase
)
Enum.Parse メソッド (Type, String, Boolean) (System) | MSDN
enum MyEnum { A, B, C }

public class MyClass
{
    public void Method()
    {
        MyEnum myEnumB = (MyEnum)Enum.Parse(typeof(MyEnum), "B"); // B
        MyEnum myEnumD = (MyEnum)Enum.Parse(typeof(MyEnum), "D"); // System.ArgumentException 要求された値 'D' が見つかりませんでした。
    }
}

Parse()では、指定の文字列に一致する値が存在しないときには例外が発生します。これを戻り値で結果を知るには、次のTryParse()を用います。

public static bool TryParse<TEnum>(
    string value,
    out TEnum result
)
where TEnum : struct
Enum.TryParse(TEnum) メソッド (String, TEnum) (System) | MSDN
enum MyEnum { A, B, C }

public class MyClass
{
    public void Method()
    {
        MyEnum myEnum;
        if( Enum.TryParse<MyEnum>("B", out myEnum) )
        {
        }
        // myEnumは"B"となる

        if (Enum.TryParse<MyEnum>("D", out myEnum))
        {
        }
        // myEnumは既定値の"A"となる
    }
}

演算子

以下の演算子がサポートされます。18.6 Enum values and operations - Enums - C# language specification | Microsoft Learn

  • ==, !=, <, >, <=, >=
  • binary +
  • binary -
  • ^, &, |
  • ~
  • ++, --
  • sizeof
enum MyEnum { A, B }


MyEnum a = MyEnum.A;
a.ToString(); // "A"

a++;
a.ToString(); // "B"

a++;
a.ToString(); // "2"

列挙型のメンバーの反復

GetNames()で列挙型のすべての名前を、GetValues()ですべての値を得られます。

Array values = Enum.GetValues(typeof(MyEnum));
foreach (object value in values)
{
    string name = value.ToString();
    int number = (int)value;
}
列挙メンバーの反復処理 - Enum クラス (System) | Microsoft Learn
Microsoft Learnから検索