You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无分配地将泛型类型转换为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:12:54