3
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”类型的操作数。

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

4

3 回答 3

4

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

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

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

请注意我的答案的上下文:
如果您想为您可以控制的任意课程提供您的课程,Alexey 有正确的答案。但是,如果您想将类与,或之类的类型
一起使用,他的回答并不适用,因为您无法向它们添加接口。Squaredoublefloatint

于 2013-07-10T07:49:59.373 回答
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,它将在运行时失败

于 2013-07-10T08:02:44.997 回答
3

您可以将其替换为方法.Multiply(T a, T b) 并将其与接口一起使用

public interface IMultiplyable<T>
{
     T Multiply(T a, T b);
}
于 2013-07-10T07:47:20.393 回答