如何在泛型类中使用二进制乘法运算符*?

时间:2013-07-10 07:43:48

标签: c# generics

abstract class Shape<T>
{
    public abstract T Area();
}
class Square<T> : Shape<T>
{
    T side;
    public Square(T side)
    {
        this.side = side;
    }

    public override T Area()
    {
        return this.side * this.side;
    }
}
  

错误1运算符'*'不能应用于'T'类型和'T'类型的操作数。

编译器抛出错误,因为*没有this.side*this.side。如何在泛型类中使用二进制乘法运算符*

3 个答案:

答案 0 :(得分:4)

你做不到。没有为所有类型定义乘法运算符。但是你的泛型没有约束,因此编译器必须假设你的类的使用者可以使用任何类型,例如string

不幸的是,.NET中的泛型约束不能用于表达这种要求,即没有办法将T仅限制为定义乘法运算符的类型。

底线是:您不能在场景中使用泛型。您需要使用与Size(适用于double)和SizeF(适用于float)类型的.NET框架相同的方式。

请注意我的答案背景:
如果你想为你可以控制的任意课程提供你的课程,Alexey有正确的答案 但是,如果您希望将Square类与doublefloatint类型一起使用,则他的答案不适用,因为您无法为其添加界面

答案 1 :(得分:4)

您不能使用*运算符本身,但您可以通过生成使用此运算符的表达式来解决它:

static class Operators
{
    public static T Multiply<T>(T x, T y)
    {
        return OperatorCache<T>.Multiply(x, y);
    }

    static class OperatorCache<T>
    {
        static OperatorCache()
        {
            Multiply = MakeBinaryOperator(ExpressionType.Multiply);
        }

        static Func<T, T, T> MakeBinaryOperator(ExpressionType type)
        {
            var x = Expression.Parameter(typeof(T), "x");
            var y = Expression.Parameter(typeof(T), "y");
            var body = Expression.MakeBinary(type, x, y);
            var expr = Expression.Lambda<Func<T, T, T>>(body, x, y);
            return expr.Compile();
        }

        public readonly static Func<T, T, T> Multiply;


    }
}

然后您可以像这样使用它:

public override T Area()
{
    return Operators.Multiply(this.side, this.side);
}

当然,您可以将其他运算符添加到Operators类;请记住如果您使用的运算符没有为T定义,它将在运行时失败

答案 2 :(得分:3)

您可以使用方法.Multiply(T a, T b)替换它 并将其与界面

一起使用
public interface IMultiplyable<T>
{
     T Multiply(T a, T b);
}