简体   繁体   中英

Is this possible? Specify any generic type as long as the + operation is defined on it

I'm not sure if this is possible, but if it is then it would be useful.

I am attempting to program in a class called Matrix<T> . The intent is to be able to have matrices of various data types, such as integers, floats, doubles, etc.

I now want to define addition:

    public static Matrix<T> operator +(Matrix<T> first, Matrix<T> second)
    {
        if (first.dimension != second.dimension)
        {
            throw new Exception("The matrices' dimensions do not match");
        }
        Matrix<T> add = new Matrix<T>(first.dimension);

        for (int i = 1; i <= first.rows; i++)
        {
            for (int j = 1; j <= first.columns; i++)
            {
                add[i,j] = first[i,j] + second[i,j];
            }
        }
        return add;
    }

There is an issue with the line add[i,j] = first[i,j] + second[i,j];since the operation + is not defined on a general object of type T .

I only want to specify matrices where T is a type such that addition is defined, however. So, I can make a matrix of int s, float s, double s, etc. but if I were to try and define a matrix of, say, int[] s, I would want this to throw an exception since + is not defined for int[] s.

So, instead of writing T , is there some way of telling the computer "this can take in any generic type, as long as an operator + is defined on the type? Or, is this not possible and I would have to sepeately define a matrix of int s, matrix of float s, and so on?

Edit: I don't see how the linked question from closure is related to this - I see nothing about operators there. If they are related, can somebody explain how?

Currently it is not possible but with preview features enabled and System.Runtime.Experimental you can use IAdditionOperators to restrict T to have + operator defined. I would say that adding this interface also to Matrix itself can be a good idea:

class Matrix<T> : IAdditionOperators<Matrix<T>, Matrix<T>, Matrix<T>> where T : IAdditionOperators<T, T, T>
{
   public static Matrix<T> operator +(Matrix<T> left, Matrix<T> right)
    {
        // swap to real implementation here
        T x = default;
        T y = default;
        Console.WriteLine(x + y);
        return default;
    }
}

See also:

It's possible using reflection

class Int
{
    readonly int v;

    public int Get => v;

    public Int(int v)
    {
        this.v = v;
    }

    public static Int operator +(Int me, Int other) => new Int(me.v + other.v);
}


class Arr<T>
{
    T[] _arr;

    public Arr(T[] arr)
    {
        _arr = arr;
    }

    public T this[int index] => _arr[index];

    public static Arr<T> operator+(Arr<T> me, Arr<T> other)
    {
        var addMethod = typeof(T).GetMethod("op_Addition");
        if (addMethod == null)
            throw new InvalidOperationException($"Type {typeof(T)} doesn't implement '+' operator");
        var result = me._arr.Zip(other._arr)
            .Select(elements => addMethod.Invoke(null, new object[] { elements.First, elements.Second }))
            .Cast<T>()
            .ToArray();
        return new Arr<T>(result);
    }
}

[Test]
public void TestAdd()
{
    var firstArray = new Arr<Int>(new[] { new Int(1), new Int(2) });
    var secondArray = new Arr<Int>(new[] { new Int(2), new Int(3) });
    var sum = firstArray + secondArray;
    Assert.AreEqual(3, sum[0].Get);
    Assert.AreEqual(5, sum[1].Get);
}

Reduced the example to array. Unfortunetly it compiles even if T doesn't implement add operator, so you will get a exception in runtime. You could also check if the add method has proper signature (returns T and takes two T's). If you need help understanding the code, let me know!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM