2009-04-24 91 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)*不支持*运营商。所以这*会起作用,但会变慢。 – 2009-04-24 11:51:41

+2

对不起 - 我应该更清楚一点。动态仍然不会让你在泛型类型上做它,它可以让你*动态*动态_然后_做任何支持它的操作。如果最终用户只想使用正确的操作符(删除所有编译检查),那么这很好。如果他们想要获得远远接近基元或结构的性能(可能的情况),他们不会。 – ShuggyCoUk 2009-04-24 13:41:11

回答

0

您可以重载一个操作符,但编译器无法知道如何添加两个未知的泛型类型(T + T),并且不能添加约束,因为操作符是静态成员。

一种方法做到这一点([编辑] in .Net 2.0)将有一个工厂的所有运营商的方法在你的矩阵的静态构造函数,这将创建一个正确的实现值类型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>