忍ばないノート

UnityやC#をメインに、開発記やTipsを書いています

【C#】enumのToStringやParse等の操作を低コストで楽にするクラス

はじめに

今回はenumの操作を低コストに抑え、且つ楽にするクラス紹介したいと思います。

よくあるもの

enumの操作に関して、特にToString()が遅いだのなんだのという話がたまに聞こえてきます。
実際、特に対策もしないで書いたコードだとboxingが発生したり、リフレクションが走ってしまいます。
それに対する対策として、定義したEnumに対するToString拡張メソッドを定義、自動生成する方法とかよくありますね。
こんなのとか

enum ECurrencyType
{
    None,
    JPY,
    USD,
    EUR,
    GBP,
    CHF,
}

public static string ToString ( this ECurrencyType self )
{
    switch ( self )
    {
        case ECurrencyType.None: return "None";
        case ECurrencyType.JPY:  return "JPY";
        case ECurrencyType.USD:  return "USD";
        case ECurrencyType.EUR:  return "EUR";
        case ECurrencyType.GBP:  return "GBP";
        case ECurrencyType.CHF:  return "CHF";
    }

    return "";
}

めんどくさい

enumの型の種類が少ないなら別に良いと思うのですが、
ゲームとか作っていると大量に定義したりされていたりしていて、
いちいち定義するのも、自動生成してコンパイル時間を待つのもめんどうです。
更に、定義済みのenumに手を加えるものなら。。。(白目
あと個人的に、enum操作するコードが冗長に感じられ、書くのがめんどくさかったりします(オイ

こんなのとか

enum ECurrencyType
{
    None,
    JPY,
    USD,
    EUR,
    GBP,
    CHF,
}

// enumを整数へ
var enum2Int = ( int ) ECurrencyType.JPY;

// 整数をenumへ
var int2Enum = ( ECurrencyType ) 2;

// 文字列をenumへ
Enum.TryParse<ECurrencyType>( "EUR", out var string2Enum );

// enumを文字列へ
var enum2String = ECurrencyType.GBP.ToString ();

楽する

っというわけで楽したいと思います。
まずはソースを。

EnumHelper.cs

(ここをクリック or タップで展開・格納可)

使い方

処理自体は隠蔽されている内部クラスが行うので、公開されているメソッドを呼ぶだけで一通りの操作ができるようになっています。
下記がEnumHelper使用のサンプルコードになります。

enum ECurrencyType
{
    None,
    JPY,
    USD,
    EUR,
    GBP,
    CHF,
}

// 32bit整数へ
int int32 = EnumHelper.ToInt32 ( ECurrencyType.JPY );

// 64bit整数へ
long int64 = EnumHelper.ToInt64 ( ECurrencyType.USD );

// 整数からenumへ
ECurrencyType euro = EnumHelper.ToValue <ECurrencyType> ( 3 );

// enumから文字列へ
string name = EnumHelper.GetName ( ECurrencyType.GBP );

// 文字列からenumへ
ECurrencyType currency = EnumHelper.TryParse <ECurrencyType> ( "CHF" ) ?? ECurrencyType.None;

※ Unityで使うときは、Project Settings > Player > Other Settings > Allow 'unsafe' code にチェックを入れて下さい。 setting on the Unity

終わりに

内部クラスの実装をみるとわかりますが、変換元のポインターを取ってきて、目的の型に変換しているのでBoxingが発生することなく、結構高速に動作します。
後はキャスト式や演算子が不要だったり、参照渡しもする必要がないので、シンプルなコードを書きやすくなるのではないかと思います。

参考

qiita.com

ufcpp.net