无分配地将泛型类型转换为Half值的实现方案
解决方案
核心思路是利用.NET 7+支持的**typeof(T)类型模式匹配**(完全兼容.NET 8 AOT),针对每个预校验的支持类型做显式转换,避免反射、动态代码或装箱操作,实现无分配的类型转换与读写。
1. Write方法实现(T → Half)
通过类型匹配直接处理每个支持的类型,将T显式转换为Half后写入BinaryWriter:
public void Write(BinaryWriter writer, T value) { Half halfValue = typeof(T) switch { Type t when t == typeof(int) => Half(Unsafe.As<T, int>(ref value)), Type t when t == typeof(long) => Half(Unsafe.As<T, long>(ref value)), Type t when t == typeof(float) => Half(Unsafe.As<T, float>(ref value)), Type t when t == typeof(double) => Half(Unsafe.As<T, double>(ref value)), Type t when t == typeof(Half) => Unsafe.As<T, Half>(ref value), _ => throw new InvalidOperationException($"Unsupported type {typeof(T)}") }; writer.Write(halfValue); }
说明:
- 使用
Unsafe.As直接操作内存,实现无分配的类型转换,避免装箱拆箱; - 构造函数已预校验支持类型,运行时不会触发非法分支。
2. Read方法实现(Half → T)
从BinaryReader读取Half后,通过类型匹配转换为目标T类型:
public T Read(BinaryReader reader) { Half halfValue = reader.ReadHalf(); return typeof(T) switch { Type t when t == typeof(int) => Unsafe.As<int, T>(ref Unsafe.AsRef<int>((int)(float)halfValue)), Type t when t == typeof(long) => Unsafe.As<long, T>(ref Unsafe.AsRef<long>((long)(float)halfValue)), Type t when t == typeof(float) => Unsafe.As<float, T>(ref Unsafe.AsRef<float>((float)halfValue)), Type t when t == typeof(double) => Unsafe.As<double, T>(ref Unsafe.AsRef<double>((double)halfValue)), Type t when t == typeof(Half) => Unsafe.As<Half, T>(ref halfValue), _ => throw new InvalidOperationException($"Unsupported type {typeof(T)}") }; }
说明:
Half转数值类型时先转成float(无损转换),再转为目标类型;- 全程无堆分配,所有分支静态可分析,完全适配.NET 8 AOT发布。
3. 完整泛型类示例
using System; using System.IO; using System.Runtime.CompilerServices; public class ValueCollection<T> where T : struct, IConvertible { public ValueCollection() { // 构造函数预校验支持的类型 Type t = typeof(T); if (t != typeof(int) && t != typeof(long) && t != typeof(float) && t != typeof(double) && t != typeof(Half)) { throw new ArgumentException($"Unsupported type {t}", nameof(T)); } } public void Write(BinaryWriter writer, T value) { Half halfValue = typeof(T) switch { Type t when t == typeof(int) => Half(Unsafe.As<T, int>(ref value)), Type t when t == typeof(long) => Half(Unsafe.As<T, long>(ref value)), Type t when t == typeof(float) => Half(Unsafe.As<T, float>(ref value)), Type t when t == typeof(double) => Half(Unsafe.As<T, double>(ref value)), Type t when t == typeof(Half) => Unsafe.As<T, Half>(ref value), _ => throw new InvalidOperationException($"Unsupported type {typeof(T)}") }; writer.Write(halfValue); } public T Read(BinaryReader reader) { Half halfValue = reader.ReadHalf(); return typeof(T) switch { Type t when t == typeof(int) => Unsafe.As<int, T>(ref Unsafe.AsRef<int>((int)(float)halfValue)), Type t when t == typeof(long) => Unsafe.As<long, T>(ref Unsafe.AsRef<long>((long)(float)halfValue)), Type t when t == typeof(float) => Unsafe.As<float, T>(ref Unsafe.AsRef<float>((float)halfValue)), Type t when t == typeof(double) => Unsafe.As<double, T>(ref Unsafe.AsRef<double>((double)halfValue)), Type t when t == typeof(Half) => Unsafe.As<Half, T>(ref halfValue), _ => throw new InvalidOperationException($"Unsupported type {typeof(T)}") }; } }
关键特性验证
- 无分配:全程使用
Unsafe.As直接操作内存,无装箱拆箱或堆分配; - AOT兼容:
typeof(T)的模式匹配在.NET 8 AOT下会被静态编译为分支判断,无运行时反射; - 类型安全:构造函数已预校验类型,运行时不会出现非法类型分支;
- 性能最优:直接类型转换与分支判断,性能接近手写非泛型代码。
内容的提问来源于stack exchange,提问作者ygoe
相关产品推荐
相关产品推荐

