Implementing arithmetic in generics?

Is it possible to implement basic arithmetic (at least adding) in C # generics, as you can with C ++ templates ? I tried to get them and work for a while, but C # does not allow you to declare the same generic type several times as you can with templates.

An extensive search did not give an answer.

EDIT: Thank you, but what I'm looking for is a way to do arithmetic at compile time by incorporating something like church numbers into generic types. That is why I linked the article I made. Arithmetic in generic types, not arithmetic for instances of generic types.

+10
source share
4 answers

Unfortunately, you cannot use arithmetic operations on generic types

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

will not work in C #!

But you can create your own numeric types and overload operators (arithmetic, equalities and implicit , explicit ). This allows you to work with them in a completely natural way. However, you cannot create an inheritance hierarchy with generalizations. You will have to use a non-universal base class or interface.

I just did it with a vector type. Short version here:

 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); } } 
+6
source

Please feel free to offer more clarification if my answer seems awkward.

There are no general restrictions for operators in C #, at least. Since John Skeet has proven that Unconstrained Melody , restrictions can really be valid in the CLR itself.

The best you can do with restrictions is to provide interfaces / user classes that expose the actions you need. You will not be able to provide a primitive (if you may not be executing the implicit operator), but it will at least allow you to create common code for the mathematical part.

Common constraints allow the compiler to infer available members based on the lowest common denominator (as defined by a constraint or absence). In most cases, generics are unlimited and therefore only give you the semantics of object .


Alternatively, avoid using restrictions and use dynamic to temporarily store a shared variable, and then make the assumption (using duck input) that it has the corresponding operators:
 class Program { static void Main(string[] args) { var result = Add<int, long, float>(1, 2); Console.WriteLine(result); // 3 Console.WriteLine(result.GetType().FullName); // System.Single Console.Read(); } static T3 Add<T1, T2, T3>(T1 left, T2 right) { dynamic d1 = left; dynamic d2 = right; return (T3)(d1 + d2); } } 

This is DLR-related and will have some performance overhead (I don't have exact numbers), especially if you assume that the calculations will be performance critical.


I'm not sure what you mean by "declare the same generic type multiple times", this works:
 class Tuple<T1, T2> // etc. var myTuple = new Tuple<int, int>(1, 2); 
+4
source

Friends, the intuitive answer to this in C # is RTTI and dropping back and forth from an object class

 enter code here class MyMath { public static T Add<T>(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<double>(3.6, 2.12)); return 0; } } 
0
source

yes, this can be done using dynamic type variables.

Example:

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

click here for more help

0
source

All Articles