C# の enum(列挙型)は、関連する定数に名前を付けてまとめる値型です。マジックナンバーの排除やコードの可読性向上に役立ちます。本記事では基本から、ストレージサイズの指定、System.Enum が提供するユーティリティ、[Flags] 属性を使ったビットフラグ、ビット演算の実践まで順に解説します。
基本
enum キーワードに続けて型名とメンバを列挙するだけで定義できます。
enum Direction
{
North,
East,
South,
West
}
メンバには既定で 0 から始まる整数値が自動的に割り当てられます。
Console.WriteLine((int)Direction.North); // 0
Console.WriteLine((int)Direction.East); // 1
Console.WriteLine((int)Direction.South); // 2
Console.WriteLine((int)Direction.West); // 3
値を明示的に指定する
任意のメンバに値を指定できます。指定されなかったメンバは、直前のメンバの値 +1 になります。
enum HttpStatus
{
Ok = 200,
Created = 201,
BadRequest = 400,
Unauthorized = 401,
NotFound = 404,
InternalServerError = 500
}
switch との組み合わせ
enum は switch 式と相性が良く、網羅性チェックも働きます。
Direction dir = Direction.North;
string label = dir switch
{
Direction.North => "北",
Direction.East => "東",
Direction.South => "南",
Direction.West => "西",
_ => "不明"
};
ストレージサイズ(基底型の指定)
enum の基底型はデフォルトで int(32 ビット整数)です。コロン(:)で明示的に変更できます。
enum SmallFlag : byte { A = 1, B = 2, C = 4 }
enum MediumFlag : ushort { X = 1, Y = 2, Z = 4 }
enum BigFlag : long { Huge = 1L << 40 }
指定できる基底型は byte・sbyte・short・ushort・int・uint・long・ulong の整数型のみです(float や char は不可)。
| 基底型 | サイズ | 値の範囲 | 主な用途 |
|---|---|---|---|
byte |
1 バイト | 0〜255 | メモリを節約したい小さなフラグ |
short |
2 バイト | −32768〜32767 | 中程度の列挙 |
int |
4 バイト | 約 ±21 億 | デフォルト。一般用途 |
long |
8 バイト | 約 ±922 京 | 64 ビットフラグが必要な場合 |
基底型を絞るメリット
- 配列や構造体に格納するときメモリを節約できる
- ネットワーク通信やバイナリ形式でのシリアライゼーションで型を合わせられる
byteを指定すると0〜255の範囲しか持てないため、不正な値を弾きやすくなる
System.Enum — 列挙型のユーティリティ
すべての enum は System.Enum 抽象クラスを継承しています。System.Enum は名前と値の変換・検証を行う静的メソッドを提供します。
Enum.GetName / Enum.GetNames
string? name = Enum.GetName(typeof(Direction), 0);
Console.WriteLine(name); // North
string[] names = Enum.GetNames(typeof(Direction));
// ["North", "East", "South", "West"]
C# 10 以降はジェネリック版が使えます。
string? name = Enum.GetName<Direction>(Direction.North); // "North"
string[] names = Enum.GetNames<Direction>();
Enum.GetValues
foreach (Direction d in Enum.GetValues<Direction>())
{
Console.WriteLine(d); // North / East / South / West
}
Enum.IsDefined
整数値や文字列が enum の有効なメンバかどうかを確認します。
Console.WriteLine(Enum.IsDefined<Direction>((Direction)1)); // True
Console.WriteLine(Enum.IsDefined<Direction>((Direction)99)); // False
外部入力から enum に変換する場合は必ずチェックしましょう。
Enum.Parse / Enum.TryParse
文字列を enum 値に変換します。
Direction d = Enum.Parse<Direction>("East");
Console.WriteLine(d); // East
if (Enum.TryParse<Direction>("West", out Direction result))
{
Console.WriteLine(result); // West
}
TryParse は変換できなかった場合に false を返すため、外部入力に対しては TryParse を推奨します。
ToString
enum 変数を文字列に変換する最も簡単な方法です。
Direction d = Direction.South;
Console.WriteLine(d.ToString()); // "South"
Console.WriteLine($"{d}"); // "South"(補間文字列も同じ)
Flags 属性 — ビットフラグとしての enum
[Flags] 属性を付けると、enum 値をビットフィールド(ビットの組み合わせ)として扱えます。複数の選択肢を同時に有効にする設定値などに便利です。
定義
各メンバの値を 2 の累乗(1, 2, 4, 8, …)にするのが基本です。
[Flags]
enum Permission
{
None = 0,
Read = 1, // 0001
Write = 2, // 0010
Execute = 4, // 0100
Delete = 8, // 1000
}
None = 0 は「何も持たない」状態を表すために慣例として定義します。
複合メンバーの定義
よく使う組み合わせに名前を付けることもできます。
[Flags]
enum Permission
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
Delete = 8,
// 複合メンバー
ReadWrite = Read | Write, // 0011 = 3
All = Read | Write | Execute | Delete // 1111 = 15
}
ToString の挙動
[Flags] を付けると ToString() が組み合わせた名前を返します。
Permission p = Permission.Read | Permission.Write;
Console.WriteLine(p); // "Read, Write"([Flags] なし だと "3")
Bitwise オペレーション
ビットフラグを実際に操作するにはビット演算子を使います。
| OR — フラグを追加する
Permission p = Permission.Read;
p = p | Permission.Write; // Read + Write を付与
// 短縮形
p |= Permission.Execute; // さらに Execute を追加
Console.WriteLine(p); // "Read, Write, Execute"
& AND — フラグを確認する
Permission p = Permission.Read | Permission.Write;
bool canRead = (p & Permission.Read) != 0; // true
bool canWrite = (p & Permission.Write) != 0; // true
bool canDelete = (p & Permission.Delete) != 0; // false
HasFlag メソッドを使うとより読みやすく書けます。
bool canRead = p.HasFlag(Permission.Read); // true
~ NOT と & AND — フラグを削除する
特定のフラグを外したい場合は ~(ビット反転)と &= を組み合わせます。
Permission p = Permission.Read | Permission.Write | Permission.Execute;
p &= ~Permission.Write; // Write を削除
Console.WriteLine(p); // "Read, Execute"
^ XOR — フラグをトグルする
フラグが立っていれば消し、立っていなければ付けます。
Permission p = Permission.Read | Permission.Write;
p ^= Permission.Write; // Write をトグル(→ 消える)
Console.WriteLine(p); // "Read"
p ^= Permission.Write; // 再度トグル(→ 戻る)
Console.WriteLine(p); // "Read, Write"
演算子まとめ
| 演算子 | 用途 | 例 |
|---|---|---|
| / |= |
フラグを追加 | p |= Permission.Write |
& |
フラグを確認 | (p & Permission.Read) != 0 |
&= + ~ |
フラグを削除 | p &= ~Permission.Write |
^ / ^= |
フラグをトグル | p ^= Permission.Execute |
まとめ
| トピック | ポイント |
|---|---|
| 基本 | 関連定数に名前を付けて可読性を上げる |
| 基底型 | byte 〜 long で型サイズを制御できる |
System.Enum |
GetNames・IsDefined・TryParse などのユーティリティを活用する |
[Flags] |
値を 2 の累乗にして複数フラグを 1 変数で管理する |
| Bitwise | | 追加・& 確認・&= ~ 削除・^ トグル |
[Flags] enum はパーミッション・状態フラグ・オプション設定など、複数の状態を同時に保持したいケースで効果的です。ビット演算と組み合わせて使いこなしましょう。