在generics中实现算术?

是否可以在C#generics中实现基本算法(至少是加法),就像使用C ++模板一样 ? 我已经尝试了一段时间来让它们起作用,但是C#不允许你多次声明相同的generics类型,就像你可以使用模板一样。

广泛的谷歌搜索没有提供答案。

编辑:谢谢,但我正在寻找的是一种在编译时进行算术运算的方法,在generics类型中嵌入像教会数字这样的东西。 这就是为什么我把我做过的文章联系起来的原因。 generics类型的算术,而不是generics类型实例的算术。

遗憾的是,您无法对generics类型使用算术运算

 T Add(T a, T b) { return a + b; // compiler error here } 

不会在c#中工作!

但是您可以创建自己的数字类型并重载运算符(算术相等和implicitexplicit )。 这使您可以以一种非常自然的方式使用它们。 但是,您无法使用generics创建inheritance层次结构。 您将不得不使用非generics基类或接口。

我只是用矢量类型做到了。 这是一个缩短版本:

 public class Vector { private const double Eps = 1e-7; public Vector(double x, double y) { _x = x; _y = y; } private double _x; public double X { get { return _x; } } private double _y; public double Y { get { return _y; } } public static Vector operator +(Vector a, Vector b) { return new Vector(a._x + b._x, a._y + b._y); } public static Vector operator *(double d, Vector v) { return new Vector(d * v._x, d * v._y); } public static bool operator ==(Vector a, Vector b) { if (ReferenceEquals(a, null)) { return ReferenceEquals(b, null); } if (ReferenceEquals(b, null)) { return false; } return Math.Abs(a._x - b._x) < Eps && Math.Abs(a._y - b._y) < Eps; } public static bool operator !=(Vector a, Vector b) { return !(a == b); } public static implicit operator Vector(double[] point) { return new Vector(point[0], point[1]); } public static implicit operator Vector(PointF point) { return new Vector(point.X, point.Y); } public override int GetHashCode() { return _x.GetHashCode() ^ _y.GetHashCode(); } public override bool Equals(object obj) { var other = obj as Vector; return other != null && Math.Abs(other._x - _x) < Eps && Math.Abs(other._y - _y) < Eps; } public override string ToString() { return String.Format("Vector({0:0.0000}, {1:0.0000})", _x, _y); } } 

如果我的回答似乎不合适,请随时提供更多说明。

至少,C#语言中的运算符没有通用约束。 正如Jon Skeet已经在Unconstrained Melody中certificate的那样, 约束实际上可能在CLR本身中完全有效。

使用约束可以做的最好的事情是提供接口/自定义类,以显示您需要的操作。 您将无法提供原语(除非您也可能实现implicit运算符),但它至少可以让您为数学部分创建通用代码。

通用约束允许编译器基于最小公分母(由约束或缺少指定)推断可用成员。 大多数情况下,generics不受约束,因此只给出object语义。


或者 ,避免使用约束并使用dynamic临时存储generics变量,然后进行假设(通过duck typing)它具有相关的运算符:

 class Program { static void Main(string[] args) { var result = Add(1, 2); Console.WriteLine(result); // 3 Console.WriteLine(result.GetType().FullName); // System.Single Console.Read(); } static T3 Add(T1 left, T2 right) { dynamic d1 = left; dynamic d2 = right; return (T3)(d1 + d2); } } 

这涉及到DLR并且会有一些性能开销(我没有确切的数字),特别是如果你打算计算性能至关重要的话。


我不确定你的意思是“多次声明相同的generics类型”,这有效:

 class Tuple // etc. var myTuple = new Tuple(1, 2); 

朋友们,在C#中对此的直观回答是RTTI并在对象类中来回转换

 enter code here class MyMath { public static T Add(T a, T b) where T: struct { switch (typeof(T).Name) { case "Int32": return (T) (object)((int)(object)a + (int)(object)b); case "Double": return (T)(object)((double)(object)a + (double)(object)b); default: return default(T); } } } class Program { public static int Main() { Console.WriteLine(MyMath.Add(3.6, 2.12)); return 0; } } 

是的,它可以通过使用动态类型变量来完成。

例:

 T Add(T value1, T value2) { dynamic a = value1; dynamic b = value2; return (a + b); } 

如需更多参考,请点击此处