2014-09-15 4 views
1

좋아, 나는이 두 가지 특정 유형, ComplexNumber<T>Matrix<T>을 구현해야합니다. Trational number, real number 또는 정수 중 하나 일 수 있습니다.수학 및 제네릭

시스템 네임 스페이스에서 실수 (decimal), 정수 (int 또는 long)에 대한 올바른 표현이 있습니다. Numerics.ComplexNumber은 내부적으로 RealPartImaginaryPartdouble인데이 유형의 표현 오류를 감당할 수 없습니다.

이제 probem은 generic 매개 변수 T을 수학적 "유효한"유형으로 제한 할 수있는 방법이 없습니다. 즉, 다음을 수행 할 수 없습니다.

public struct ComplexNumber<T> 
{ 
    readonly T realPart; 
    readonly T imaginaryPart; 

    public static ComplexNumber<T> Add(ComplexNumber<T> left, ComplexNumber<T> right) 
    { 
     return new ComplexNumber<T>(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 } 
} 

그리고 Matrix<RationalNumber> 또는 Matrix<ComplexNumber> 일하는 것이 지금은 두 가지 가능성을 마련했습니다.

다른 옵션은 인터페이스를 통해 그것을 할 수 있습니다 :

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); 
    } 

인터페이스 옵션은 구조체 느릅 나무가 IMHO, 프레임 워크 구현하는 방법을 숫자 유형과 일관성, 그대로 나를 RationalNumber을 구현할 수 있습니다. 또한 유형 자체는 매우 가볍고 일반적으로 수명이 짧습니다. Numeric 기본 클래스 솔루션은 훨씬 더 헤비급 것 같아,하지만 난 정말 그 때 정확히 다른 통해 하나의 장점을 정량화 할 수있는 전문가가 아니에요에 :

  • 코드 qualitiy와 미래의 확장 성 및 유지 보수
  • 성능 및 메모리 사용량 (다른 무엇보다도 호기심)
  • 더 나은 해결책이 있습니까?

누군가가 약간의 빛을 비출 수 있다면, 나는 그것을 고맙게 생각합니다.

+5

가 왜 처음에이 일반적인하기를? 10 진수로 수정하십시오. 필요한 모든 것을 제공합니다. – DavidG

+2

분자가 10의 요소 인 경우를 제외하고 소수는 이성의 훌륭한 표현이 아닙니다 ... – tolanj

+0

INumeric Add (숫자 오른쪽); 귀하의 인터페이스 예제에서 모두 INUMeric 매개 변수를 사용해야합니다 ... – tolanj

답변

0

당신은이 문제를 해결하기 위해 확장 방법을 사용할 수 있습니다 :

public struct ComplexNumber<T> 
{ 
    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<int> Add(this ComplexNumber<int> self, ComplexNumber<int> other) 
    { 
     return new ComplexNumber<int>(self.RealPart + other.RealPart, self.ImaginaryPart + other.ImaginaryPart); 
    } 

    public static ComplexNumber<double> Add(this ComplexNumber<double> self, ComplexNumber<double> other) 
    { 
     return new ComplexNumber<double>(self.RealPart + other.RealPart, self.ImaginaryPart + other.ImaginaryPart); 
    } 

    // Add similar extension methods for each numeric type you need 
} 

이처럼 사용

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