数学和generics

好的,我需要实现这两种特殊类型: ComplexNumberMatrixT可以是以下之一: 有理数 , 实数或整数。

在System命名空间中,我对实数( decimal ),整数( intlong )有很好的表示。 Numerics.ComplexNumber不会削减它,因为内部RealPartImaginaryPartdouble ,在这种特殊情况下,我不能承受这种类型的表示错误。

现在,探测器当然是没有办法将通用参数T约束到数学“有效”类型。 也就是说,我不能做到以下几点:

 public struct ComplexNumber { readonly T realPart; readonly T imaginaryPart; public static ComplexNumber Add(ComplexNumber left, ComplexNumber right) { return new ComplexNumber(left.realPart + right.realPart, left.imaginaryPart + right.imaginaryPart); //Compile time error. No operator defined for T } } 

所以我需要一个解决方法。 虽然性能本身并不是目标,但我希望代码能够合理地运行,但最重要的是,我希望它能成为最优雅的解决方案。 现在我想出了两种可能性:

一个Numeric抽象基类,类似于:

 public abstract class Numeric { protected abstract Numeric _Add(Numeric right); protected abstract Numeric _Subtract(Numeric right); public static Numeric Add(Numeric left, Numeric right) { return _Add(this, right); } public static Numeric Subtract(Numeric left, Numeric right) { return _Subtract(this, right); } 

现在我能做到:

 public sealed class RationalNumber: Numeric { readonly long numerator, denominator; protected override Numeric _Add(Numeric right) { //Rational addition implementation } } 

然后MatrixMatrix将起作用。

另一种选择是通过接口来完成:

 public INumeric { INumeric Add(INumeric right); INumeric Subtract(INumeric right); } public struct RationalNumber: INumeric { readonly long numerator, denominator; public static RationalNumber Add(RationalNumber left, RationalNumber right) { //Rationa add implementation } INumeric INumeric.Add(INumeric right) //explicit to not clog up the type and to convey the idea of a framework mechanism. { if (!(right is RationalNumber)) throw new ArgumentException(); Add(this, (RationalNumber)right); } 

接口选项允许我将RationalNumber实现为一个结构,即恕我直言,更符合框架中数字类型的实现方式。 这些类型本身也非常轻巧,通常寿命很短。 Numeric基类解决方案看起来像是一个更重要的重量级,但是我并不是一个专家来准确量化一个优于另一个的优势:

  • 代码质量和未来的可扩展性和维护
  • 性能和内存消耗(好奇心比什么都重要)
  • 更好的解决方案?

如果有人可以轻松一点,我会很感激。

您可以使用扩展方法来解决此问题:

 public struct ComplexNumber { private readonly T _realPart; private readonly T _imaginaryPart; public ComplexNumber(T realPart, T imaginaryPart) { _realPart = realPart; _imaginaryPart = imaginaryPart; } public T RealPart { get { return _realPart; } } public T ImaginaryPart { get { return _imaginaryPart; } } public override string ToString() { return string.Format("({0}, {1})", RealPart, ImaginaryPart); } } public static class ComplexNumberExtensions { public static ComplexNumber Add(this ComplexNumber self, ComplexNumber other) { return new ComplexNumber(self.RealPart + other.RealPart, self.ImaginaryPart + other.ImaginaryPart); } public static ComplexNumber Add(this ComplexNumber self, ComplexNumber other) { return new ComplexNumber(self.RealPart + other.RealPart, self.ImaginaryPart + other.ImaginaryPart); } // Add similar extension methods for each numeric type you need } 

像这样用它:

 var first = new ComplexNumber(1, 2); var second = new ComplexNumber(3, 4); var result = first.Add(second); Console.WriteLine(result);