MS_EnumDefinition - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki
- 戻る(.NET開発)
列挙型(Enum)の定義とビット演算(C# の例)
enum 列挙型名
{
メンバー1,
メンバー2,
…,
メンバーn
}enum 列挙型名 : 内部的な型
{
メンバー1 = メンバー1の値,
メンバー2 = メンバー2の値,
…,
メンバーn = メンバーnの値
}補足(値を明示すべき場面): 値を省略すると 0 から順に採番される。
このため、
- メンバーを途中に挿入すると、以降の値がすべてずれる、
- DB やファイルに数値で永続化していると、既存データの意味が変わる、
という事故が起きる。
// 危険:Beta を足すと Released の値が 1 → 2 に変わる enum Status { Alpha, Beta, Released } // 安全:明示しておく enum Status { Alpha = 1, Beta = 2, Released = 3 }永続化する enum は必ず値を明示するのが原則。
なお、既定の基になる型は
intで、
: byte: longなどで変更できる。
ビット演算で 32 個を超えるフラグが要る場合はlongにする。
-
FlagsAttribute 属性を使用すると、ビット演算も可能になる。
-
列挙型(Enum)のビット演算でプロファイルを組み立てるなどする場合に使える。
-
参考
-
定義
-
利用
-
移行メモ(
[Flags]の役割): 正確には、
[Flags]が無くてもビット演算自体はできる
(enum は数値なので|や&が使える)。
[Flags]が変えるのは主に次の 2 点である。
[Flags]なし[Flags]ありToString()一致する名前が無ければ数値( 5)"Read, Write"と列挙されるHasFlag()使える(が意味が曖昧) 意図が明確になる 読み手への意思表示 無し 「組み合わせて使う」と分かる [Flags] enum Permission { None = 0, // 0 は必ず None として用意する Read = 1 << 0, // 1 Write = 1 << 1, // 2 Execute = 1 << 2, // 4 All = Read | Write | Execute } var p = Permission.Read | Permission.Write; bool canWrite = p.HasFlag(Permission.Write); // true bool canWrite2 = (p & Permission.Write) != 0; // こちらの方が速い要点:
- 値は 2 の冪(
1 << n)にする。連番にすると重なって壊れる。0はNone(HasFlag(0)は常に true になるため、判定に使わない)。HasFlagはボックス化を伴うため、性能が要る場面では&を使う。
ToString() 高速化(.NET の Reflection)
- Reflection だから遅いらしい。
- メソッドを動的生成してキャッシュさせる高速化の技法がある。
補足(なぜ遅いのか / 現在の対処):
Enum.ToString()は
メタデータから名前を検索するため、内部でリフレクションが働く。
ループ内で大量に呼ぶと無視できないコストになる。原文が言う「メソッドを動的生成してキャッシュ」は、
式木 やReflection.Emitで
switch 相当のデリゲートを作る手法である。補足(現在の選択肢):
手段 備考 Dictionary<TEnum, string>に事前展開最も単純で効果的 nameof定数が決まっているなら最速(コンパイル時に解決) [EnumMember]+ ソース ジェネレーターシリアライズ用途 Enum.GetName<T>(T)(.NET 8+)ジェネリック版でボックス化を回避 近年の .NET では
Enum系 API 自体が最適化されており、
まず計測してから対処するのが妥当である。
- 列挙型 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
https://ufcpp.net/study/csharp/st_enum.html - 連載:C# 入門 第16回 列挙型の活用 - @IT
https://www.atmarkit.co.jp/fdotnet/csharp_abc/csharp_abc_016/csharp_abc01.html
- 列挙型 (C# リファレンス)
https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/enum - 列挙型のデザイン
https://learn.microsoft.com/ja-jp/dotnet/standard/design-guidelines/enum
Tags: 移行, .NET開発, ASP.NET