enumの変換にEnum.ToObjectを使わない
「enum int 変換」などで検索すると、intからenumに変換するにはEnum.ToObjectを使うと説明している記事が出てきます。しかしEnum.ToObjectを使うのは極めて無駄です。単純にintの前に(型名)を付けてキャストできます。これはC#のリファンレンスでも使われています。
計測してみる
Enum.ToObjectを使うと実行時のパフォーマンスも非常に悪いです。BenchmarkDotNetを使った以下のコードで計測してみます。
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
[ShortRunJob(RuntimeMoniker.CoreRt60)]
[MemoryDiagnoser]
[MaxColumn, MinColumn, MeanColumn, MedianColumn]
public class CastToEnum
{
public enum E
{
A,
B,
C,
}
[Benchmark]
public E CastDirectly()
{
return InternalCastDirectly(0);
}
private E InternalCastDirectly(int i)
{
return (E)i;
}
[Benchmark]
public E CastEnumToObject()
{
return InternalCastEnumToObject(0);
}
private E InternalCastEnumToObject(int i)
{
return (E)Enum.ToObject(typeof(E), i);
}
}
結果は以下の通りです。直接キャストしたCastDirectlyは速すぎてほとんど計測不能ですがEnum.ToObjectを使ったCastEnumToObjectは60nsもかかっています。
しかも24バイトのメモリアロケーションまで発生しています。これはEnum.ToObjectがobject型で返すためにボックス化が発生しているからです。
InternalCastDirectlyをコンパイルしたILは以下となっています。引数のiを読み込んで返しているだけです。enumとintのバイト列は全く同じなので何もする必要がありません。
IL_0000: ldarg.1
IL_0001: ret
他の整数型からenumに変換も問題なくできます。InternalCastDirectlyの引数をintからlongに変えるとILは以下になります。
IL_0000: ldarg.1
IL_0001: conv.i4
IL_0002: ret
コンパイラが適切に認識してconv.i4でint型にキャストされるようになっています。
まとめ
以上のようにenum型はただの数値型と同じようにキャストできます。Enum.ToObjectが必要になる場面はほとんど存在しません。必ずキャストを使ってください。