C# の enum に関連する小技。

# enum の値を対応する任意の文字列に変換する

画面に表示や印刷するときなど、enum値を文字列に変換したいときがあります。  
そういうとき、C#ではenumに対しても拡張メソッドを定義することが可能なので、enum値を表示用の文字列に
変換する拡張メソッドを定義しておくと便利です。

例えば、

```csharp
// enum定義
enum Gender { Unknown, Male, Female };
```

というenum定義に対して、

```csharp
// enum定義のヘルパクラス
static class GenderExt
{
  // Gender に対する拡張メソッドの定義
  public static string DisplayName(this Gender gender)
  {
    string[] names = { "不明", "男性", "女性" };
    return names[(int)gender];
  }
}
```

という静的クラスを定義すると、

```csharp
Console.WriteLine(Gender.Male.DisplayName()); // => '男性' と出力される。
```

という感じで使うことができます。

# 数値がenumで定義済みかどうかチェックする

外部からの入力値などをenum値に変換するときなど、値がキャスト可能かどうか事前に確認したい時があります。  
そういう場合、Enumクラスの静的メソッド`IsDefined`で値が定義済かどうかチェックすることができます。

[MSDN:Enum.IsDefined メソッド ](http://msdn.microsoft.com/ja-jp/library/system.enum.isdefined\(v=vs.110\).aspx)
> public static bool IsDefined(
 	Type enumType,
 	Object value
)

使い方は以下のような感じで。

```csharp
int n = 1 // 入力値
if (Enum.IsDefined(typeof(Gender), n))
    Console.WriteLine(Gender);
else
    Console.WriteLine("Undefined");
```

実行すると、

> Male

と表示される筈です。

# enumの値を列挙する

enumで定義された値を列挙したいしたい場合、Enumクラスの静的メソッド `GetValues`
を用いることで、定義済みの値を配列で受け取ることができます。

[MSDN:Enum.GetValues メソッド](http://msdn.microsoft.com/ja-jp/library/system.enum.getvalues\(v=vs.110\).aspx)
> public static Array GetValues(
	Type enumType
 )

戻り値は Array なので、そのまま foreach に渡すことができます。

```csharp
foreach (var gender in Enum.GetValues(typeof(Gender)))
{
    Console.WriteLine(gender.DisplayName());
}
```

実行すると、

> 不明
男性
女性

と表示される筈です。

# サンプルプログラム

上記内容を簡単なヘルパクラスにまとめてみました。

```csharp
// enum定義
enum Gender { Unknown, Male, Female };

// enum定義のヘルパクラス
static class GenderExt
{
    // Gender に対する拡張メソッドの定義
    public static string DisplayName(this Gender gender)
    {
        string[] names = { "不明", "男性", "女性" };
        return names[(int)gender];
    }

    // 整数値が enum で定義済みかどうか？
    public static bool IsDefined(int n)
    {
        return Enum.IsDefined(typeof(Gender), n);
    }

    // Foreach用のGetEnumeratorを持つヘルパクラス
    public class EnumerateGenders
    {
        public IEnumerator<Gender> GetEnumerator()
        {
            foreach (var gender in Enum.GetValues(typeof(Gender)))
                yield return gender;
        }
    }

    // enum定義をforeachに渡すためのヘルパクラスを返す
    public static EnumerateGenders Enumerate()
    {
        return new EnumerateGenders();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // enumを文字列に変換する。
        Console.WriteLine("{0} => {1}", Gender.Unknown, Gender.Unknown.DisplayName());

        // 整数値がenumの値として定義済みかチェックする
        int n = 1;
        if (GenderExt.IsDefined(n))
            Console.WriteLine("整数値:{0}は{1}として定義されています。", n, ((Gender)n).ToString());
        else
            Console.WriteLine("整数値：{0}は未定義です。", n);

        // 定義済みのenumを列挙する
        foreach (var gender in GenderExt.Enumerate())
        {
            Console.WriteLine("{0}:{1}", gender.DisplayName(), (int)gender);
        }
    }
}
```

実行すると

> Unknown => 不明
整数値:1はMaleとして定義されています。
不明:0
男性:1
女性:2

と表示される筈です。

実際のプログラムで利用する場合、拡張メソッドとそれ以外のユーティリティ的なメソッドでクラスを分割し、ユーティリティ的なメソッドは汎用的に使えるようにジェネリッククラスとして記述するほうが良いでしょう。

```csharp
// ジェネリックを利用した汎用ヘルパクラス
static class EnumUtil<T>
{
    // 整数値が enum で定義済みかどうか？
    public static bool IsDefined(int n)
    {
        return Enum.IsDefined(typeof(T), n);
    }

    // Foreach用のGetEnumeratorを持つヘルパクラス
    public class EnumerateEnum
    {
        public IEnumerator<T> GetEnumerator()
        {
            foreach (T e in Enum.GetValues(typeof(T)))
                yield return e;
        }
    }

    // enum定義をforeachに渡すためのヘルパクラスを返す
    public static EnumerateEnum Enumerate()
    {
        return new EnumerateEnum();
    }
}
```

使い方は

```csharp
foreach (var gender in EnumUtil<Gender>.Enumerate())
{
    Console.WriteLine(gender)
}
```

という感じ。

さらに、`using`を利用して

```csharp
using GenderUtil = EnumUtil<Gender>;
```

という感じに別名を定義するとより使いやすくなります。