public class Racional<T>
{
private T nominator;
private T denominator;
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
Run Code Online (Sandbox Code Playgroud)
我对这部分感兴趣:
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
Run Code Online (Sandbox Code Playgroud)
怎么了:
二元运算符的参数之一必须是包含类型
我如何能够对数学运算中的这部分进行规范编码?
编译器错误解释了代码无法编译的原因。包含类型是泛型类型定义,从此类类型构造的泛型类型不被视为相同类型。
我有几个问题:
Rational类型必须是泛型?有理数定义为可以表示为两个整数的商/分数的数字(其中分母不是0)。为什么不使该类型成为非泛型并简单地int在整个过程中使用?或者您是否打算将该类型用于其他整数类型,例如long和BigInteger?在这种情况下,如果您想要某种代码共享机制,请考虑使用类似阿利斯塔德的建议。无论如何,您似乎希望能够“一般地”添加“可添加”类型的两个实例。不幸的是,目前没有任何方法可以在 C# 中表达“有合适的加法运算符”约束。
方法 #1: C# 4 中的一种解决方法是使用类型dynamic为您提供所需的“虚拟运算符”语义。
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = (dynamic)a.Nominator + b.Nominator;
var denominatorSum = (dynamic)a.Denominator + b.Denominator;
return new Racional<T>(nominatorSum, denominatorSum);
}
Run Code Online (Sandbox Code Playgroud)
如果该类型没有合适的加法运算符,该运算符将抛出异常。
方法#2:另一种(更有效)的方法是使用表达式树。
首先,创建并缓存一个委托,该委托可以通过编译适当的表达式来执行加法:
private readonly static Func<T, T, T> Adder;
static Racional()
{
var firstOperand = Expression.Parameter(typeof(T), "x");
var secondOperand = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(firstOperand, secondOperand);
Adder = Expression.Lambda<Func<T, T, T>>
(body, firstOperand, secondOperand).Compile();
}
Run Code Online (Sandbox Code Playgroud)
(如果类型没有合适的加法运算符,静态构造函数将抛出异常。)
然后在运算符中使用它:
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = Adder(a.Nominator, b.Nominator);
var denominatorSum = Adder(a.Denominator, b.Denominator);
return new Racional<T>(nominatorSum, denominatorSum);
}
Run Code Online (Sandbox Code Playgroud)