帮助课堂上的数学操作数(c#)

use*_*895 7 c# class operands

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)

怎么了:

二元运算符的参数之一必须是包含类型

我如何能够对数学运算中的这部分进行规范编码?

Ani*_*Ani 3

编译器错误解释了代码无法编译的原因。包含类型是泛型类型定义,从此类类型构造的泛型类型不被视为相同类型。

我有几个问题:

  1. 为什么Rational类型必须是泛型?有理数定义为可以表示为两个整数的商/分数的数字(其中分母不是0)。为什么不使该类型成为非泛型并简单地int在整个过程中使用?或者您是否打算将该类型用于其他整数类型,例如longBigInteger?在这种情况下,如果您想要某种代码共享机制,请考虑使用类似阿利斯塔德的建议。
  2. 为什么两个有理数的乘积等于它们的分子之和除以分母之和?这对我来说没有意义。

无论如何,您似乎希望能够“一般地”添加“可添加”类型的两个实例。不幸的是,目前没有任何方法可以在 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)