C#における列挙型の定義、活用、およびデータ変換の実装

列挙型の基礎と定義

列挙型(enum)は、一連の名前付き定数を定義するための値型であり、enum キーワードを使用して宣言します。各シンボルは整数値に対応しており、既定では最初の要素が 0、その後の要素は順に 1 ずつ増加した整数値が割り当てられます。コードの可読性を高め、型安全性を確保するために広く利用されています。

// 定義例:注文のステータス
public enum OrderStatus
{
    Pending = 0,  // 待機中
    Shipped = 1   // 出荷済み
}

値を明示的に指定せず、最初の要素だけに値を設定することも可能です。この場合、未設定の要素には直前の要素の値に 1 を加えた値が自動的に割り当てられます。

public enum OrderStatus
{
    Pending = 0,
    Shipped   // 自動的に 1 が割り当てられる
}

データベースおよびUI設計での活用

データベース設計において、例えばユーザーテーブルの「権限レベル」のようなフィールドは、通常 int 型や tinyint 型で数値として格納されます(例:0が一般、1が管理者)。プログラムコード内では、マジックナンバー(数値リテラル)を直接使用するよりも、列挙型を使用することで可読性が大幅に向上します。

また、検索条件としてこれらの値をドロップダウンリストなどで表示する場合、列挙型の定義を辞書形式(Key: 表示名, Value: 数値)のコレクションに変換し、UI コントロールにバインドする必要があります。これにより、画面表示と内部ロジックの整合性を保ちながら開発を進めることができます。

基本型との相互変換

開発現場では、列挙型、整数(int)、文字列(string)の間でデータをやり取りするシナリオが頻繁に発生します。以下に LogLevel 列挙型を用いた変換の実装例を示します。

public enum LogLevel
{
    Info = 0,
    Warning = 1,
    Error = 2
}

public void ConversionExample()
{
    var currentStatus = LogLevel.Error; // 型は LogLevel

    // 1. 列挙型から整数への変換
    int statusCode = (int)currentStatus; 
    // 結果: 2

    // 2. 列挙型から文字列への変換
    string statusName = currentStatus.ToString(); 
    // 結果: "Error"

    // 3. 文字列から列挙型への変換
    LogLevel parsedStatus = (LogLevel)Enum.Parse(typeof(LogLevel), "Warning");
    // 結果: LogLevel.Warning

    // 4. 文字列から対応する整数値への変換
    int parsedValue = (int)Enum.Parse(typeof(LogLevel), "Info");
    // 結果: 0

    // 5. 整数から列挙型への変換
    LogLevel statusFromInt = (LogLevel)1;
    // 結果: LogLevel.Warning

    // 6. 整数から列挙型の名称(文字列)への変換
    string nameFromInt = Enum.GetName(typeof(LogLevel), 2);
    // 結果: "Error"

    // 7. 列挙型のすべての値を反復処理
    foreach (LogLevel level in Enum.GetValues(typeof(LogLevel)))
    {
        Console.WriteLine($"{level.ToString()} - {(int)level}");
    }
}

汎用ヘルパーメソッドによる辞書変換

UI コントロールへのデータバインディングを簡素化するために、任意の列挙型を Dictionary<string, int> に変換する汎用的な拡張メソッドを実装します。これにより、特定の列挙型ごとに変換ロジックを記述する手間を省くことができます。

public enum Department
{
    Sales,
    Engineering,
    HR
}

public static class EnumExtensions
{
    /// <summary>
    /// 整数値から列挙型の名称を取得します。
    /// </summary>
    public static string GetNameFromValue<T>(this int value) where T : Enum
    {
        return Enum.GetName(typeof(T), value);
    }

    /// <summary>
    /// 列挙型のメンバー名を配列として取得します。
    /// </summary>
    public static string[] GetNames<T>() where T : Enum
    {
        return Enum.GetNames(typeof(T));
    }

    /// <summary>
    /// 列挙型を「名称(キー), 値(バリュー)」の辞書コレクションに変換します。
    /// </summary>
    public static Dictionary<string, int> ToNameValueDictionary<T>() where T : Enum
    {
        var result = new Dictionary<string, int>();
        var names = Enum.GetNames(typeof(T));

        foreach (var name in names)
        {
            // 文字列名から列挙型の値を解析し、辞書に追加
            var parsed = Enum.Parse(typeof(T), name);
            result.Add(name, Convert.ToInt32(parsed));
        }
        return result;
    }

    /// <summary>
    /// LINQを使用した、より簡潔な辞書変換実装
    /// </summary>
    public static Dictionary<string, int> ToDictionary<T>() where T : Enum
    {
        return Enum.GetValues(typeof(T))
                   .Cast<int>()
                   .ToDictionary(
                       value => Enum.GetName(typeof(T), value),
                       value => value
                   );
    }
}

以下は、上記ヘルパークラスを使用した実行例です。

public void HelperExample()
{
    // 整数から名称への変換
    var deptName = EnumExtensions.GetNameFromValue<Department>(1);
    Console.WriteLine($"ID: 1, Name: {deptName}"); // 出力: ID: 1, Name: Engineering

    // 方法1: 辞書への変換 (ToNameValueDictionary)
    var dict1 = EnumExtensions.ToNameValueDictionary<Department>();
    foreach (var item in dict1)
    {
        Console.WriteLine($"{item.Key} => {item.Value}");
    }

    // 方法2: 辞書への変換 (ToDictionary using LINQ)
    var dict2 = EnumExtensions.ToDictionary<Department>();
    foreach (var item in dict2)
    {
        Console.WriteLine($"{item.Key} => {item.Value}");
    }
}

Web API向けのオブジェクトコレクションへの変換

フロントエンド側へ選択肢データを提供する場合など、単なる辞書ではなく、JSON形式に変換しやすいオブジェクト(例: { Name: "...", Value: ... })のリストが必要になることがあります。以下に列挙型を匿名型のコレクションに変換し、シリアライズ可能な状態にする例を示します。

public enum FeedbackRating
{
    Satisfied = 1,
    VerySatisfied,
    Excellent
}

// 変換処理の実装
var feedbackData = Enum.GetValues(typeof(FeedbackRating))
                       .Cast<FeedbackRating>()
                       .Select(r => new 
                       { 
                           Name = r.ToString(), 
                           Value = (int)r 
                       })
                       .ToList();

このコレクションを JSON シリアライザ(例: System.Text.Json)に通すと、以下のような構造のデータが出力されます。

[
  {
    "Name": "Satisfied",
    "Value": 1
  },
  {
    "Name": "VerySatisfied",
    "Value": 2
  },
  {
    "Name": "Excellent",
    "Value": 3
  }
]

タグ: C# Enum 型変換 データバインディング System.Text.Json

5月20日 17:50 投稿