私はパーティーにかなり遅れていることを知っていますが、このような安全なキャストを行う必要がある場合は、 を使用して次のように使用できますDelegate.CreateDelegate
。
public static int Identity(int x){return x;}
// later on..
Func<int,int> identity = Identity;
Delegate.CreateDelegate(typeof(Func<int,TEnum>),identity.Method) as Func<int,TEnum>
書き込みReflection.Emit
や式ツリーがなくても、ボックス化またはボックス化解除せずに int を enum に変換するメソッドがあります。TEnum
here には基になる型が必要であることに注意してくださいint
。そうしないと、バインドできないという例外がスローされます。
編集:あまりにも機能し、書くのが少し少ないかもしれない別の方法...
Func<TEnum,int> converter = EqualityComparer<TEnum>.Default.GetHashCode;
これは、32 ビット以下の列挙型を TEnum から int に変換するために機能します。その逆ではありません。.Net 3.5+ では、EnumEqualityComparer
基本的にこれを return に変換するように最適化されてい(int)value
ます。
デリゲートを使用するとオーバーヘッドが発生しますが、ボクシングよりは確実に優れています。
これはかなり古いものでしたが、まだここに戻ってきて、.net 5/.Net コア (または unsafe パッケージを使用した netfx) で動作し、最適なソリューションを探している場合は...
[JitGeneric(typeof(StringComparison), typeof(int))]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryConvert<TEnum, T>(this TEnum @enum, out T val)
where TEnum : struct, Enum
where T : struct, IConvertible, IFormattable, IComparable
{
if (Unsafe.SizeOf<T>() == Unsafe.SizeOf<TEnum>())
{
val = Unsafe.As<TEnum, T>(ref @enum);
return true;
}
val = default;
return false;
}
使用例は次のようになります::
public static int M(MethodImplOptions flags) => flags.TryConvert(out int v) ? v : 0;
ここで、sharplab で、このメソッドが完全にインライン化されていることがわかります::
https://sharplab.io/#gist:802b8d21ee1de26e791294ba48f69d97