C#の列挙型へのキャストint に似ていますが、私の列挙型はGeneric Typeパラメーターです。これを処理するbest方法は何ですか?
例:
private T ConvertEnum<T>(int i) where T : struct, IConvertible
{
return (T)i;
}
コンパイラエラーCannot convert type 'int' to 'T'
を生成します
完全なコードは次のとおりです。値にはintまたはnullを含めることができます。
private int? TryParseInt(string value)
{
var i = 0;
if (!int.TryParse(value, out i))
{
return null;
}
return i;
}
private T? TryParseEnum<T>(string value) where T : struct, IConvertible
{
var i = TryParseInt(value);
if (!i.HasValue)
{
return null;
}
return (T)i.Value;
}
私が見つけた最も簡単な方法は、object
にキャストを追加することにより、コンパイラーの手を強制することです。
return (T)(object)i.Value;
ランタイムが静的ジェネリッククラスの複数のインスタンスを作成するという事実を悪用する非常に高速なソリューションを次に示します。あなたの内側の最適化デーモンを解き放ちます!
これは、ストリームからEnumsを一般的な方法で読んでいるときに本当に輝いています。列挙型の基になる型をキャッシュする外部クラスとBitConverterを組み合わせて、すばらしいものを解き放ちます。
void Main()
{
Console.WriteLine("Cast (reference): {0}", (TestEnum)5);
Console.WriteLine("EnumConverter: {0}", EnumConverter<TestEnum>.Convert(5));
Console.WriteLine("Enum.ToObject: {0}", Enum.ToObject(typeof(TestEnum), 5));
int iterations = 1000 * 1000 * 100;
Measure(iterations, "Cast (reference)", () => { var t = (TestEnum)5; });
Measure(iterations, "EnumConverter", () => EnumConverter<TestEnum>.Convert(5));
Measure(iterations, "Enum.ToObject", () => Enum.ToObject(typeof(TestEnum), 5));
}
static class EnumConverter<TEnum> where TEnum : struct, IConvertible
{
public static readonly Func<long, TEnum> Convert = GenerateConverter();
static Func<long, TEnum> GenerateConverter()
{
var parameter = Expression.Parameter(typeof(long));
var dynamicMethod = Expression.Lambda<Func<long, TEnum>>(
Expression.Convert(parameter, typeof(TEnum)),
parameter);
return dynamicMethod.Compile();
}
}
enum TestEnum
{
Value = 5
}
static void Measure(int repetitions, string what, Action action)
{
action();
var total = Stopwatch.StartNew();
for (int i = 0; i < repetitions; i++)
{
action();
}
Console.WriteLine("{0}: {1}", what, total.Elapsed);
}
最適化を有効にしたCore i7-3740QMの結果:
Cast (reference): Value
EnumConverter: Value
Enum.ToObject: Value
Cast (reference): 00:00:00.3175615
EnumConverter: 00:00:00.4335949
Enum.ToObject: 00:00:14.3396366
これにはEnum.Parse
を使用できるはずです。
return (T)Enum.Parse(typeof(T), i.Value.ToString(), true);
この記事では、拡張メソッドの汎用列挙の解析について説明します。
あるいは、enumをジェネリック型としてではなく、Typeとして取得できる場合は、単に使用します
Enum.ToObject
https://msdn.Microsoft.com/en-us/library/system.enum.toobject(v = vs.110).aspx
public static class Extensions
{
public static T ToEnum<T>(this int param)
{
var info = typeof(T);
if (info.IsEnum)
{
T result = (T)Enum.Parse(typeof(T), param.ToString(), true);
return result;
}
return default(T);
}
}