如何使二进制乘法运算符 * 在泛型类中可用
本文关键字:泛型类 运算符 何使 二进制 | 更新日期: 2023-09-27 18:21:42
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
的*
。如何使二进制乘法运算符*
在泛型类中可用?
不能使用 *
运算符本身,但可以通过生成使用此运算符的表达式来解决它:
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
定义,它将在运行时失败。
你不能
那样做。并非所有类型都定义了乘法运算符。但是泛型没有约束,因此编译器必须假定类的使用者可以使用任何类型,例如string
。
遗憾的是,.NET 中的泛型约束不能用于表达这种要求,即无法将T
限制为仅定义乘法运算符的类型。
底线是:不能在方案中使用泛型。您需要采用与.NET框架相同的方式,包括其Size
(对于double
(和SizeF
(对于float
(类型。
注意我的答案的上下文:
如果你想为你控制的任意类提供你的类,阿列克谢有正确的答案。
但是,如果您想将Square
类与double
,float
或int
等类型一起使用,他的答案则不适用,因为您无法向它们添加接口。
你可以用方法替换它.Multiply(T a, T b)
并与界面一起使用
public interface IMultiplyable<T>
{
T Multiply(T a, T b);
}