はじめに
C#でEnumを使うとき、int値ではなく、文字に変換して使いたいということがあります。
これをどのように実現するか、一つの実例を書かせていただきます。
またほかにも便利になりそうなメソッドも記載しています。
ちなみにここではサンプルなのでコンソールで作っています。
enumサンプルコード
とりあえず、こんな感じのenumで試していきます。
public enum SampleEnum
{
Tokyo,
Nagoya,
Sapporo,
Osaka
}
ありがちな方法
このままenum値を表示させるとこんな感じ
static void Main(string[] args)
{
Console.WriteLine("enum値のままで表示させた場合");
Console.WriteLine(SampleEnum.Tokyo);
Console.WriteLine(SampleEnum.Nagoya);
Console.WriteLine(SampleEnum.Sapporo);
Console.WriteLine(SampleEnum.Osaka);
Console.ReadLine();
}
結果
勉強をはじめたばかりだと、enumは分かるけど、実際にView(Window)に反映させたり、ComboBoxのItesSourceに使うときには、文字で表現したいけど、どうしたらいいかわからないということがあります。自分もそうでした。
たとえば、こんな感じでいちいち文字に変換したりとか...
static void Main(string[] args)
{
Console.WriteLine("enum値のままで表示させた場合");
Console.WriteLine(SampleEnum.Tokyo);
Console.WriteLine(SampleEnum.Nagoya);
Console.WriteLine(SampleEnum.Sapporo);
Console.WriteLine(SampleEnum.Osaka);
Console.WriteLine();
Console.WriteLine("enum値をCase変換してみた");
Console.WriteLine(GetName(SampleEnum.Tokyo));
Console.WriteLine(GetName(SampleEnum.Nagoya));
Console.WriteLine(GetName(SampleEnum.Sapporo));
Console.WriteLine(GetName(SampleEnum.Osaka));
Console.ReadLine();
}
/// <summary>
/// enum値を日本語に変換します
/// </summary>
/// <param name="sampleEnum"></param>
/// <returns></returns>
static string GetName(SampleEnum sampleEnum)
{
switch (sampleEnum)
{
case SampleEnum.Tokyo:
return "東京";
case SampleEnum.Nagoya:
return "名古屋";
case SampleEnum.Sapporo:
return "札幌";
case SampleEnum.Osaka:
return "大阪";
default:
return null;
}
}
結果
これでも別にいいのですが、ただ、このenumが複数のところで使われていて、変更があった時などは、面倒だったりします。
特に変換メソッドが複数のところで書かれてしまうと、エラーの原因になります。
Descriptionを使いましょう
Microsoft DocumentにDescriptionAttribute クラスというものがあります
このDescriptionはプロパティやイベントの説明文として使うものですが、これを読み込んで、stringに変換して使ってしまおうということです。
この辺りはググるとたくさんのサンプルが出てくるので、調べるだけでも勉強になると思います。
記事書きながら検索したらたとえばこんなのがありました
Convert Enum to String in C#
Enum Description to String
[C#] enum値に文字列情報を紐付ける方法
で、さきほどのサンプルコードにDescriptionを付加するとこんな感じになります。
ちなみに、この後使用するメソッドがわかりやすくなるように値をセットしています
using System.ComponentModel; //これが必要です
public enum SampleEnum
{
[Description("東京")]
Tokyo = 1,
[Description("名古屋")]
Nagoya = 3,
[Description("札幌")]
Sapporo = 5,
[Description("大阪")]
Osaka = 7
}
enum用のメソッドを作る
ここに紹介するメソッドは自分に使いやすいようにしたものですので、使い勝手は人によると思います。ご自身の開発に合わせていろいろと修正をしていただければと思います。
enum値からDescriptionを取得するメソッド
Descriptionからenum値を取得するメソッド
int値からDescriptionを取得するメソッド
int値からenum値を取得するメソッド
enum値のリストを取得するメソッド
Descriptionのリストを取得するメソッド
をヘルパークラスとしてまとめています。メソッドで型指定も行っています。
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
namespace EnumSample
{
public static class EnumHelper
{
/// <summary>
/// 列挙体フィールドのDescriptionを取得する。
/// </summary>
/// <param name="value">列挙体値</param>
/// <returns>Description文字列</returns>
public static string GetEnumDescriptionFromValue<T>(object value)
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
string description = null;
if (value != null)
{
string strValue = value.ToString();
description = strValue;
if (strValue.Length > 0)
{
FieldInfo fieldInfo = type.GetField(strValue);
// Descriptionが複数ある場合はこちらのコードにします
//var attrebutes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
//var dcs = attrebutes.Select(x => x.Description).FirstOrDefault();
//if(dcs != null)
//{
// description = dcs;
//}
Attribute attribute = Attribute.GetCustomAttribute(fieldInfo, typeof(DescriptionAttribute));
if (attribute != null)
{
DescriptionAttribute descriptionAttribute = (DescriptionAttribute)attribute;
description = descriptionAttribute.Description;
}
}
}
return description;
}
/// <summary>
/// Descriptionから列挙体の値を取得する
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="description"></param>
/// <returns></returns>
public static T GetEnumValueFromDescription<T>(string description)
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
FieldInfo[] fields = type.GetFields();
var field = fields
.SelectMany(f => f.GetCustomAttributes(typeof(DescriptionAttribute), false),
(f, a) => new { Field = f, Att = a })
.Where(a => ((DescriptionAttribute)a.Att)
.Description == description).SingleOrDefault();
return field == null ? default(T) : (T)field.Field.GetRawConstantValue();
}
/// <summary>
/// int値からDescriptionを取得する
/// 逆は(int)enum value で取得できます
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static string GetEnumDescriptionFromInt<T>(int value)
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
var enumValue = (T)Enum.ToObject(type, value);
return GetEnumDescriptionFromValue<T>(enumValue);
}
/// <summary>
/// int値からenum value値を取得する
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T GetEnumValueFromInt<T>(int value)
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
return (T)Enum.ToObject(type, value);
}
/// <summary>
/// enumの値リストを取得
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static List<T> GetEnumList<T>()
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
List<T> values = new List<T>();
foreach (T value in Enum.GetValues(type))
{
values.Add(value);
}
return values;
}
/// <summary>
/// enumのDescripntionリストを取得
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static List<string> GetEnumDescriptionList<T>()
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
List<string> descriptions = new List<string>();
foreach (T value in Enum.GetValues(type))
{
var description = GetEnumDescriptionFromValue<T>(value);
descriptions.Add(description);
}
return descriptions;
}
}
}
メソッドを使った例
実際にメソッドを使って、コーディングしてみます
static void Main(string[] args)
{
Console.WriteLine();
Console.WriteLine("enum値のままで表示させた場合");
Console.WriteLine(SampleEnum.Tokyo);
Console.WriteLine(SampleEnum.Nagoya);
Console.WriteLine(SampleEnum.Sapporo);
Console.WriteLine(SampleEnum.Osaka);
Console.WriteLine();
Console.WriteLine("enum値をCase変換してみた");
Console.WriteLine(GetName(SampleEnum.Tokyo));
Console.WriteLine(GetName(SampleEnum.Nagoya));
Console.WriteLine(GetName(SampleEnum.Sapporo));
Console.WriteLine(GetName(SampleEnum.Osaka));
Console.WriteLine();
Console.WriteLine("GetEnumDescriptionFromValueを使ってTokyoのDescriptionを取得");
var tokyo = EnumHelper.GetEnumDescriptionFromValue<SampleEnum>(SampleEnum.Tokyo);
Console.WriteLine(tokyo);
Console.WriteLine();
Console.WriteLine("GetEnumValueFromDescriptionを使ってDescriptionからenum値を取得");
var nagoya = EnumHelper.GetEnumValueFromDescription<SampleEnum>("名古屋");
Console.WriteLine(nagoya);
Console.WriteLine();
Console.WriteLine("GetEnumDescriptionFromIntを使ってint値からDescriptionを取得");
var sapporo = EnumHelper.GetEnumDescriptionFromInt<SampleEnum>(5);
Console.WriteLine(sapporo);
Console.WriteLine();
Console.WriteLine("GetEnumValueFromIntを使ってint値からenum値を取得");
var osaka = EnumHelper.GetEnumValueFromInt<SampleEnum>(7);
Console.WriteLine(osaka);
Console.WriteLine();
Console.WriteLine("GetEnumListを使ってenumの値リストを取得");
var enums = EnumHelper.GetEnumList<SampleEnum>();
foreach(var e in enums)
Console.WriteLine(e);
Console.WriteLine();
Console.WriteLine("GetEnumDescriptionListを使ってDescriptionリストを取得");
var descriptions = EnumHelper.GetEnumDescriptionList<SampleEnum>();
foreach (var d in descriptions)
Console.WriteLine(d);
Console.WriteLine();
Console.ReadLine();
}
結果がこんな感じでうまく動いてくれているのがわかります
↧