如何避免泛型枚举类型实现中的不必要装箱操作?
避免Enum.ToObject的装箱操作方案
问题背景
现有基类定义:
public abstract class EnumType<TEnum, TValue> where TEnum : struct, IConvertible where TValue : struct { public abstract TEnum GetEnumValue(TValue value); }
以及派生类:
public sealed class ByteEnumType<T> : EnumType<T, byte> where T : struct, IConvertible { public override T GetEnumValue(byte value) => (T)Enum.ToObject(typeof(T), (int)value); }
和:
public sealed class CharEnumType<T> : EnumType<T, char> where T : struct, IConvertible { public override T GetEnumValue(char value) => (T)Enum.ToObject(typeof(T), (int)value); }
上述实现中,Enum.ToObject方法会引入不必要的装箱操作,需要找到避免装箱的替代方案。
解决方案
方案1:使用Unsafe类实现无装箱转换(.NET Core/.NET 5+)
借助System.Runtime.CompilerServices.Unsafe的类型转换方法,直接在值类型间做内存级转换,完全规避装箱:
针对ByteEnumType<T>:
public sealed class ByteEnumType<T> : EnumType<T, byte> where T : struct, IConvertible { public override T GetEnumValue(byte value) { // 校验枚举底层类型与byte匹配,避免内存错误 if (Enum.GetUnderlyingType(typeof(T)) != typeof(byte)) throw new ArgumentException("枚举的底层类型必须为byte"); return Unsafe.As<byte, T>(ref value); } }
针对CharEnumType<T>:
public sealed class CharEnumType<T> : EnumType<T, char> where T : struct, IConvertible { public override T GetEnumValue(char value) { if (Enum.GetUnderlyingType(typeof(T)) != typeof(char)) throw new ArgumentException("枚举的底层类型必须为char"); return Unsafe.As<char, T>(ref value); } }
方案2:预编译表达式树(兼容更早.NET版本)
如果需要兼容.NET Framework等不支持Unsafe类的环境,可以在静态构造函数中预编译转换委托,后续调用直接执行委托,避免每次调用的装箱开销:
以ByteEnumType<T>为例:
public sealed class ByteEnumType<T> : EnumType<T, byte> where T : struct, IConvertible { private static readonly Func<byte, T> _converter; static ByteEnumType() { var param = Expression.Parameter(typeof(byte)); var convertExpr = Expression.Convert(param, typeof(T)); _converter = Expression.Lambda<Func<byte, T>>(convertExpr, param).Compile(); } public override T GetEnumValue(byte value) => _converter(value); }
内容的提问来源于stack exchange,提问作者Weifen Luo
相关产品推荐
相关产品推荐

