在通用c#结构中使用运算符

时间:2013-10-05 04:04:22

标签: c# generics

我正在编写一个通用的C#结构。我有以下内容:

struct GenericPoint<T> where T : IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T> {
  T x;
  T y;

  GenericPoint(T x, T y) {
    this.x = x;
    this.y = y;
  }

  static GenericPoint<T> operator +(GenericPoint<T> p1, GenericPoint<T> p2) {
    GenericPoint<T> r;
    r.x = (dynamic) p1.x + p2.x;
    r.y = (dynamic) p1.y + p2.y;
    return r;
  }

这会有效,但还有更好的方法吗?我的意图是T将是一个知道“+”运算符的类型。我很高兴在编译时做出这个承诺。但这可能吗?

3 个答案:

答案 0 :(得分:3)

不幸的是,C#generics无法做到这一点。

这就是为什么,例如,.NET框架提供,PointPointFRectangleRectangleF等,其中定义这些结构基本上是彼此重复的,intfloat代替了想要的“通用”类型。


但是,如果你真的想要这样做......

  1. 创建IMath<T>界面。 (或者如果你有冒险精神,甚至可能IField<T>。请看这里:Field

    interface IMath<T>
    {
        T Zero { get; }
        T One { get; }
        T Negate(T a);
        T Add(T a, T b);
        T Sub(T a, T b);
        T Mult(T a, T b);
        //etc...
    }
    
  2. 修改GenericPoint<T>static引用IMath<T>

    struct GenericPoint<T>
    {
        public static IMath<T> TMath { get; set; }
        public T x;
        public T y;
        public static GenericPoint<T> operator +(GenericPoint<T> p1, GenericPoint<T> p2)
        {
            GenericPoint<T> r;
            r.x = TMath.Add(p1.x, p2.x);
            r.y = TMath.Add(p1.y, p2.y);
            return r;
        }
    }
    
  3. 在“程序初始化”期间,为您要支持的每种类型GenericPoint<int>.TMath设置GenericPoint<float>.TMathT等。如果您不小心尝试使用某些未指定GenericPoint<T>类型的IMath<T>类,则在使用运算符时只会获得NullReferenceException

答案 1 :(得分:0)

你想做什么你不能(我希望能够做到)。问题是在C#接口中不允许运算符重载。因此,虽然您可以约束(http://msdn.microsoft.com/en-us/library/d5x73970.aspx)您的通用变量('T'),但如果将其约束到接口,它将不会知道您有一个'+'运算符。您可以使用适当的运算符重载来定义基类,但是您必须将'T'约束为基于该类(因此您不能使用任何值类型,如int,double等),或者不基于此类的对象用作约束的对象。你的动态解决方案实际上非常好,最大的问题当然是你将任何编译时警告短路,所以如果你使用一个不支持'+'的类,你就不会知道它直到运行时失败。

答案 2 :(得分:0)

有一种稍微简单的方法。使用Linq.Expressions可以创建将以通用方式执行所需数学运算的委托,假设您愿意在运行时接受错误(如果类型不支持该操作)。 这实际上更容易的唯一原因是它已经完成,请参阅:http://www.yoda.arachsys.com/csharp/miscutil/

使用Operator.cs中定义的静态Operator类,您可以用以下内容替换动态转换:

r.x = (dynamic) p1.x + p2.x;
r.y = (dynamic) p1.y + p2.y;

变为:

r.x = Operator<T>.Add(p1.x, p2.x);
r.y = Operator<T>.Add(p1.y, p2.y);
相关问题