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

如何在C#泛型类中兼容System.Numerics与DoubleNumerics的Vector3

实现支持float/double双精度的泛型Vector3类

针对你的需求,这里提供两种高效的实现方案,避免直接使用object+强制转换的低效方式:

方案一:抽象接口+适配器模式(类型安全优先)

这种方式通过定义通用接口统一两种Vector3的访问逻辑,编译时即可保证类型安全,适合需要扩展Vector3功能的场景。

1. 定义通用Vector3接口

先定义包含核心属性的接口,可根据需求添加常用方法:

public interface IVector3<T> where T : struct
{
    T X { get; set; }
    T Y { get; set; }
    T Z { get; set; }
    // 按需添加方法,如 Add、Subtract 等
}

2. 实现float/double版本的适配器

分别封装两个库的Vector3,实现通用接口,并添加隐式转换方便和原生类型互转:

Float版本适配器

using System.Numerics;

public class FloatVector3Adapter : IVector3<float>
{
    private Vector3 _innerVector;

    public FloatVector3Adapter(Vector3 vector) => _innerVector = vector;

    public float X
    {
        get => _innerVector.X;
        set => _innerVector.X = value;
    }

    public float Y
    {
        get => _innerVector.Y;
        set => _innerVector.Y = value;
    }

    public float Z
    {
        get => _innerVector.Z;
        set => _innerVector.Z = value;
    }

    // 隐式转换,直接用原生Vector3赋值/转换
    public static implicit operator Vector3(FloatVector3Adapter adapter) => adapter._innerVector;
    public static implicit operator FloatVector3Adapter(Vector3 vector) => new FloatVector3Adapter(vector);
}

Double版本适配器

using System.DoubleNumerics;

public class DoubleVector3Adapter : IVector3<double>
{
    private Vector3 _innerVector;

    public DoubleVector3Adapter(Vector3 vector) => _innerVector = vector;

    public double X
    {
        get => _innerVector.X;
        set => _innerVector.X = value;
    }

    public double Y
    {
        get => _innerVector.Y;
        set => _innerVector.Y = value;
    }

    public double Z
    {
        get => _innerVector.Z;
        set => _innerVector.Z = value;
    }

    public static implicit operator Vector3(DoubleVector3Adapter adapter) => adapter._innerVector;
    public static implicit operator DoubleVector3Adapter(Vector3 vector) => new DoubleVector3Adapter(vector);
}

3. 改造泛型MyClass

public class MyClass<T> where T : struct
{
    public IVector3<T> Coordinate { get; set; }

    // 默认构造函数,初始化对应精度的Vector3
    public MyClass()
    {
        Coordinate = typeof(T) switch
        {
            Type t when t == typeof(float) => (IVector3<T>)(object)new FloatVector3Adapter(new System.Numerics.Vector3()),
            Type t when t == typeof(double) => (IVector3<T>)(object)new DoubleVector3Adapter(new System.DoubleNumerics.Vector3()),
            _ => throw new NotSupportedException($"不支持的类型:{typeof(T)}")
        };
    }

    // 接受原生Vector3的构造函数,简化外部传入
    public MyClass(System.Numerics.Vector3 vector) where T : float
    {
        Coordinate = (IVector3<T>)(object)new FloatVector3Adapter(vector);
    }

    public MyClass(System.DoubleNumerics.Vector3 vector) where T : double
    {
        Coordinate = (IVector3<T>)(object)new DoubleVector3Adapter(vector);
    }
}

使用示例

// float精度实例
var floatObj = new MyClass<float>();
floatObj.Coordinate.X = 1.5f;
// 直接转换为原生Vector3
System.Numerics.Vector3 nativeFloatVec = floatObj.Coordinate;

// double精度实例
var doubleObj = new MyClass<double>();
doubleObj.Coordinate.Y = 3.14159;
System.DoubleNumerics.Vector3 nativeDoubleVec = doubleObj.Coordinate;

方案二:动态类型+封装(简洁优先)

如果不想编写额外的适配器类,可以利用dynamic封装类型判断逻辑,外部使用时无需手动强制转换,代码更简洁(有轻微性能损耗,高频调用需注意)。

改造后的泛型MyClass

public class MyClass<T> where T : struct
{
    private object _coordinate;

    // 对外暴露统一的X/Y/Z属性
    public T X
    {
        get => GetComponent(v => v.X);
        set => SetComponent(v => v.X = value);
    }

    public T Y
    {
        get => GetComponent(v => v.Y);
        set => SetComponent(v => v.Y = value);
    }

    public T Z
    {
        get => GetComponent(v => v.Z);
        set => SetComponent(v => v.Z = value);
    }

    public MyClass()
    {
        _coordinate = typeof(T) switch
        {
            Type t when t == typeof(float) => new System.Numerics.Vector3(),
            Type t when t == typeof(double) => new System.DoubleNumerics.Vector3(),
            _ => throw new NotSupportedException($"不支持的类型:{typeof(T)}")
        };
    }

    // 获取原生Vector3对象
    public object GetNativeVector() => _coordinate;

    // 设置原生Vector3对象
    public void SetNativeVector(object vector)
    {
        if (vector is System.Numerics.Vector3 floatVec && typeof(T) == typeof(float))
            _coordinate = floatVec;
        else if (vector is System.DoubleNumerics.Vector3 doubleVec && typeof(T) == typeof(double))
            _coordinate = doubleVec;
        else
            throw new ArgumentException("Vector类型与泛型参数不匹配");
    }

    // 封装动态访问逻辑
    private T GetComponent(Func<dynamic, T> getter) => getter((dynamic)_coordinate);
    private void SetComponent(Action<dynamic> setter) => setter((dynamic)_coordinate);
}

使用示例

var floatInstance = new MyClass<float>();
floatInstance.X = 2.718f;
// 获取原生Vector3时只需一次转换
var nativeFloat = (System.Numerics.Vector3)floatInstance.GetNativeVector();

var doubleInstance = new MyClass<double>();
doubleInstance.Z = 1.414;
var nativeDouble = (System.DoubleNumerics.Vector3)doubleInstance.GetNativeVector();

方案选择

  • 若追求类型安全且需要扩展Vector3的方法,优先选方案一;
  • 若希望代码简洁、快速完成改造,且对性能要求不极致,选方案二。

内容的提问来源于stack exchange,提问作者Denzel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 13:39:53