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);
    }
}

Leave a Comment