Cast Int to Generic Enum in C#
类似于将int强制转换为c中的枚举,但我的枚举是一个泛型类型参数。最好的方法是什么?
例子:
1 2 3 4 | private T ConvertEnum<T>(int i) where T : struct, IConvertible { return (T)i; } |
生成编译器错误
完整代码如下,其中值可以包含int或null。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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; } |
我发现的最简单的方法是通过向
1 | return (T)(object)i.Value; |
这里有一个非常快速的解决方案,它滥用了运行时创建多个静态泛型类实例的事实。释放你内在的优化恶魔!
当你以一种通用的方式从一个流中读取枚举时,这真的很亮。结合一个外部类,该类还缓存枚举的基础类型和一个bitconverter,以释放出令人敬畏的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 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); } |
启用优化的核心i7-3740qm上的结果:
1 2 3 4 5 6 | 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 |
您应该能够使用
1 |
本文讨论如何解析扩展方法的泛型枚举:
- 使用扩展方法进行泛型枚举分析
或者,如果可以将枚举不作为泛型类型而是作为类型获取,则只需使用
1 | Enum.ToObject |
https://msdn.microsoft.com/en-us/library/system.enum.toobject(v=vs.110).aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |