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

如何在C#中为双类型泛型接口指定泛型约束?

泛型Scale方法的约束与乘法运算符问题解决方案

你的核心问题是Scale<T>方法的泛型约束无法匹配IPoint<TSelf, TBase>的结构,且当前代码中T与double的乘法操作未被编译器识别。以下是两种可行的解决方案:

方案一:引入双泛型参数并利用数值类型转换

修改Scale方法,新增TBase泛型参数,约束T实现IPoint<T, TBase>,同时让TBase支持数值转换,将传入的double类型scale转换为TBase类型后再执行乘法:

using System.Numerics;

namespace Test {

    public interface IPoint<TSelf, TBase>
        where TSelf : struct, IPoint<TSelf, TBase>
        where TBase : INumber<TBase> {
        public static abstract TSelf operator *(TSelf left, TBase right);
    }

    public struct Point2<T> : IPoint<Point2<T>, T>
        where T : INumber<T> {
        public T X;
        public T Y;
        public Point2(T x, T y) { 
            X = x; Y = y; 
        }
        public static Point2<T> operator *(Point2<T> left, T right)
            => new Point2<T>(left.X * right, left.Y * right);
    }

    public static class Test {

        // 修改后的Scale方法,新增TBase泛型参数并添加约束
        public static T[] Scale<T, TBase>(T[] points, double scale)
            where T : struct, IPoint<T, TBase>
            where TBase : INumber<TBase>, IConvertible {
            var scaledValue = TBase.FromDouble(scale);
            var result = new T[points.Length];
            for (int i = 0; i < points.Length; i++)
                result[i] = points[i] * scaledValue;
            return result;
        }

        public static Point2<double>[] UseScale() {
            Point2<double>[] points = [ new (1, 1), new (2, 2) ];
            // 编译器自动推断泛型类型,无需手动指定
            return Scale(points, 2.0);
        }

    }
}

方案二:为IPoint接口新增double乘法运算符(针对性场景)

如果你的场景仅需支持与double的乘法,可以在IPoint接口中新增接受double参数的静态抽象乘法运算符,让Scale方法的约束直接匹配:

using System.Numerics;

namespace Test {

    public interface IPoint<TSelf, TBase>
        where TSelf : struct, IPoint<TSelf, TBase>
        where TBase : INumber<TBase> {
        public static abstract TSelf operator *(TSelf left, TBase right);
        // 新增double乘法运算符
        public static abstract TSelf operator *(TSelf left, double right);
    }

    public struct Point2<T> : IPoint<Point2<T>, T>
        where T : INumber<T> {
        public T X;
        public T Y;
        public Point2(T x, T y) { 
            X = x; Y = y; 
        }
        public static Point2<T> operator *(Point2<T> left, T right)
            => new Point2<T>(left.X * right, left.Y * right);
        
        // 实现double乘法运算符,将double转换为T类型
        public static Point2<T> operator *(Point2<T> left, double right)
            => left * T.CreateChecked(right);
    }

    public static class Test {

        // 现在可以直接添加约束
        public static T[] Scale<T>(T[] points, double scale)
            where T : struct, IPoint<T, INumber<T>> {
            var result = new T[points.Length];
            for (int i = 0; i < points.Length; i++)
                result[i] = points[i] * scale;
            return result;
        }

        public static Point2<double>[] UseScale() {
            Point2<double>[] points = [ new (1, 1), new (2, 2) ];
            return Scale(points, 2.0);
        }

    }
}

说明

  • 方案一通用性更强,支持所有实现INumber<TBase>的数值类型,通过IConvertible接口实现类型转换。
  • 方案二更贴合double专属场景,但需要修改接口和实现类,灵活性稍弱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:47:46