2009-04-24 9 views
2

それは私の問題だけではないようです。
私はこれらの質問を見て、私は解決策を見つけることができなかったので、私の質問を複製として閉じないでください。
汎用クラスの演算子をどのようにオーバーロードしますか?

class Matrix<T> { 
     private Int32 rows; 
     private Int32 cols; 
     private T[,] matrix; 

     public Matrix() { 
      rows = cols = 0; 
      matrix = null; 
     } 

     public Matrix(Int32 m, Int32 n) { 
      rows = m; 
      cols = n; 
      matrix = new T[m, n]; 
     } 

     public T this[Int32 i, Int32 j] { 
      get { 
       if (i < rows && j < cols) 
        return matrix[i, j]; 
       else 
        throw new ArgumentOutOfRangeException(); 
      } 
      protected set { 
       if (i < rows && j < cols) 
        matrix[i, j] = value; 
       else 
        throw new ArgumentOutOfRangeException(); 
      } 
     } 

     public Int32 Rows { 
      get { return rows; } 
     } 

     public Int32 Cols { 
      get { return cols; } 
     } 

     public static Matrix<T> operator+(Matrix<T> a, Matrix<T> b) { 
      if(a.cols == b.cols && a.rows == b.rows) { 
       Matrix<T> result = new Matrix<T>(a.rows, a.cols); 
       for (Int32 i = 0; i < result.rows; ++i) 
        for (Int32 j = 0; j < result.cols; ++j) 
         result[i, j] = a[i, j] + b[i, j]; 
       return result; 
      } 
      else 
       throw new ArgumentException("Matrixes don`t match operator+ requirements!"); 
     } 

     public static Matrix<T> operator-(Matrix<T> a, Matrix<T> b) { 
      if (a.cols == b.cols && a.rows == b.rows) { 
       Matrix<T> result = new Matrix<T>(a.rows, a.cols); 
       for (Int32 i = 0; i < result.rows; ++i) 
        for (Int32 j = 0; j < result.cols; ++j) 
         result[i, j] = a[i, j] - b[i, j]; 
       return result; 
      } 
      else 
       throw new ArgumentException("Matrixes don`t match operator- requirements!"); 
     } 

あなたはコンパイラが伝え何を知っている:「『 - 』演算子タイプ 『T』と 『T』のオペランドに適用することができない」、それがすべての演算子のためです。
だから、これのために最善の決定は何ですか?私の知る限り、インターフェースには演算子が含まれていないので、タイプTの抽象基本クラスだけですが、オペラートを抽象として定義することはできません。

+2

@ShuggyCoUk - 実際には、「ダイナミック」(C#4.0)でサポートしています。だから、これはうまくいくだろうが、遅くなるだろう。 –

+2

申し訳ありません - 私はもっと明確にすべきでした。動的でもジェネリック型ではできませんが、動的に_キャスト*して、それをサポートするものすべてに対して操作を実行できます。エンド・ユーザーが正しい演算子を使用したい場合(コンパイル・チェックをすべて削除する)、これは問題ありません。プリミティブや構造体(おそらくケース)のパフォーマンスに遠く離れたものを手に入れたいのであれば、彼らはそうしないでしょう。 – ShuggyCoUk

答えて

0

演算子をオーバーロードすることはできますが、コンパイラーは2つの未知のジェネリック型(T + T)を追加する方法を知りません。演算子は静的メンバーであるため、制約を追加できません。

これを行う方法([編集] in .Net 2.0)は、Matrixの静的コンストラクタ内のすべての演算子メソッドのファクトリを持つことになり、値型Tたとえば、TypeCodeに基づいて)、またはサポートされていない値の型の場合はNotImplementedExceptionをスローします。しかし、この方法では、コンパイル時のチェックがありません。

[編集] .Net 3.5では、実際に表現木を使用して汎用パラメータの演算子を得ることができます:http://www.yoda.arachsys.com/csharp/miscutil/usage/genericoperators.html

また、このリンクをチェックすることができます。http://msdn.microsoft.com/en-us/library/system.linq.expressions.binaryexpression.aspx

3

前の回答(すでにリンク)は、それのほとんどを説明します。関連する例(.NET 3.5ではMiscUtil) - Complex<T>

関連する問題