Implementing arithmetic in generics?

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 the operators (arithmetic, equality and implicit, explicit). This lets you work with them in a quite natural way. However you cannot create an inheritance hierarchy with generics. You will have to use a non generic base class or interface.

I just did it with a vector type. A shortened 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);
    }
}

yes, it can be done by using dynamic type variables.

example:

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

for more reference please click here


Please feel free to offer more clarification if my answer seems off-kilter.

There are no generic constraints on operators in the C# language, at least. As Jon Skeet has proven with Unconstrained Melody, the constraints might actually be perfectly valid in the CLR itself.

The best you can do with constraints is provide interfaces / custom classes that expose the actions you need. You wouldn't be able to provide the primitive (unless you also implement the implicit operator perhaps), but it would at least let you create generic code for the math part.

Generic constraints allow the compiler to infer the available members based on the lowest common denominator (as specified by the constraint or lack of). Most of the time, generics are unconstrained and thus give you only object semantics.


Alternatively, avoid using constraints and use dynamic to temporarily store the generic variable and then make the assumption (via duck typing) that it has the relevant 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 involves the DLR and will have some performance overhead (I don't have exact figures), especially if you intend the calculations to be performance-critical.


I'm not sure what you mean "declare the same generic type multiple times", this works:
class Tuple<T1, T2> // etc.

var myTuple = new Tuple<int, int>(1, 2);

Tags:

C#

.Net

Generics