如何使用泛型类的不同泛型类型的操作数来重载泛型类的运算符

时间:2014-10-29 07:32:24

标签: c# generics operator-overloading

已经提出了许多类似的问题,但都涉及相同类型或相同泛型类型的操作数。特别是这个(How can I use a generic type parameter with an operator overload?)接近我正在寻找但没有答案或解决方法。

是否可以为'*'运算符重载执行类似的操作:

public class MyNumericClass<T>
{
    public double Value { get; set; }

    //OK but works only for same type operands
    public static double operator *(MyNumericClass<T> left, MyNumericClass<T> right)
    {
        return left.Value * right.Value;
    }

    //****Pseudo Code for different type operands - not OK****
    public static double operator *<TRight>(MyNumericClass<T> left, MyNumericClass<TRight> right)
    {
        return left.Value * right.Value;
    }

    static void Test()
    {
        MyNumericClass<int> i = new MyNumericClass<int>();
        MyNumericClass<int> j = new MyNumericClass<int>();
        MyNumericClass<string> s = new MyNumericClass<string>();
        double r1 = i * j;
        double r2 = i * s; //Operator '*' cannot be applied to operands...
    }
}

我需要为不同的泛型类型设置特定的重载。在这种情况下,非泛型超类不会这样做,因为我有其他运算符的重载(这里没有显示),如果我使用超类类型的参数而不是确切的泛型类型,则会产生不明确的调用。

是否可以这样做或是否有解决方法?是否可以使用op_Multiply? (尝试过但无法使其发挥作用)。

P.S。我没有看到为什么这样的事情不可能的原因。

EDIT1 在人们的回答和评论之后,我将添加另一个版本的类,其中包含隐式转换和更多重载,以演示调用歧义以及为什么提供的答案无法解决我的问题。我需要在运算符重载中指定不同的泛型类型来解决此问题:

public class MyNumericClass<T>
{
    public double Value { get; set; }

    public static implicit operator double(MyNumericClass<T> value)
    {
        return value.Value;
    }

    public static implicit operator MyNumericClass<T>(double value)
    {
        MyNumericClass<T> c = new MyNumericClass<T>();
        c.Value = value;
        return c;
    }

    public static MyNumericClass<T> operator *(double left, MyNumericClass<T> right)
    {
        return left * right.Value;
    }

    public static MyNumericClass<T> operator *(MyNumericClass<T> left, double right)
    {
        return right * left;
    }

    //Does not resolve ambiguity and neither does a base class or interface
    public static double operator *(MyNumericClass<T> left, dynamic right)
    {
        return right * left;
    }

    //OK but work only for same type operands
    public static double operator *(MyNumericClass<T> left, MyNumericClass<T> right)
    {
        return left.Value * right.Value;
    }

    ////****Pseudo Code for different type operands - not OK****
    //public static double operator *<TRight>(MyNumericClass<T> left, MyNumericClass<TRight> right)
    //{
    //    return left.Value * right.Value;
    //}

    static void Test()
    {
        MyNumericClass<int> i = new MyNumericClass<int>();
        MyNumericClass<int> j = new MyNumericClass<int>();
        MyNumericClass<string> s = new MyNumericClass<string>();
        double r1 = i * j;
        double r2 = i * s; //The call is ambiguous...
    }
}

2 个答案:

答案 0 :(得分:1)

这实际上取决于您将来如何使用它 你可以:

创建一个包含Value的非泛型基类。然后运算符在基类上工作。

实现接口并使用协方差。

像这样:

void Main()
{
    MyNumericClass<int> i = new MyNumericClass<int>();
    MyNumericClass<int> j = new MyNumericClass<int>();
    MyNumericClass<string> s = new MyNumericClass<string>();

    double r1 = i * j;
    double r2 = i * s; 
}

public interface IMyNumericClass<out T> {
    double Value { get; set; }
}

public class MyNumericClass<T> : IMyNumericClass<T>
{
    public double Value { get; set; }

    public static double operator *(MyNumericClass<T> left, MyNumericClass<T> right)
    {
        return left.Value * right.Value;
    }

    public static double operator *(MyNumericClass<T> left, IMyNumericClass<object> right)
    {
        return left.Value * right.Value;
    }
}

答案 1 :(得分:0)

你可能需要这样做

public class MyNumericClass<T>
{
    public double Value { get; set; }

    //OK but works only for same type operands
    public static double operator *(MyNumericClass<T> left, MyNumericClass<double> right)
    {

        return left.Value * right.Value;
    }
    public static double operator *(MyNumericClass<T> left, MyNumericClass<T> right)
    {

        return left.Value * right.Value;
    }

    static void Test()
    {
        MyNumericClass<int> i = new MyNumericClass<int>();
        MyNumericClass<int> i2 = new MyNumericClass<int>();
        MyNumericClass<double> j = new MyNumericClass<double>();
        double r1 = i * i2;
        double r2 = i * j;
    }
}