47

Can someone explain why this won't work? I was trying to be able to add two values regardless of the numeric type.

public static T Add<T> (T number1, T number2)
{
    return number1 + number2;
}

When I compile this, I get the following error:

Operator '+' cannot be applied to operands of type 'T' and 'T'
Andy Evans
  • 6,997
  • 18
  • 72
  • 118
  • 1
    The C# compiler does this so you don't write buggy code. If T is unknown to the compiler it doesn't know how to add T values. It also doesn't know the result type of T, in this case the addition. – JonH Nov 14 '11 at 13:59
  • Are the arguments forced to be "of numeric type"?? – El Ronnoco Nov 14 '11 at 13:59

14 Answers14

80

There is no generic constraint that allows you to enforce operator overload. You may take a look at the following library. Alternatively if you are using .NET 4.0 you could use the dynamic keyword:

public static T Add<T>(T number1, T number2)
{
    dynamic a = number1;
    dynamic b = number2;
    return a + b;
}

Obviously this doesn't apply any compile time safety which is what generics are meant for. The only way to apply compile time safety is to enforce generic constraints. And for your scenario there is no constraint available. It's only a trick to cheat the compiler. If the caller of the Add method doesn't pass types that work with the + operator the code will throw an exception at runtime.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I think now there is where constraint.. Details [here](https://msdn.microsoft.com/en-us/library/bb384067.aspx) – Aamir Masood Mar 31 '16 at 13:14
  • 3
    @Aamir The "where" constraint has always been there. The point is that there is no way to specify "where T can be added to other Ts" in that where clause :) – flytzen May 05 '16 at 23:14
  • 1
    or simply public static dynamic Add(dynamic a, dynamic b) { return a + b; } – Sarath Jan 28 '17 at 12:56
  • But the compiler knows everywhere it is used the types that are passed to it. In which case, it would be able to create a specialization of it for all of them, and then check that all specialization of it in use have an overload for + no? – Didier A. Mar 14 '18 at 08:30
  • what will happen if number1 or number2 is null. ? – sameer Dec 10 '22 at 16:03
34

The solutions given here work well, but I thought I'd add another one which uses expressions

public static T Add<T>(T a, T b)
{
    // Declare the parameters
    var paramA = Expression.Parameter(typeof(T), "a");
    var paramB = Expression.Parameter(typeof(T), "b");

    // Add the parameters together
    BinaryExpression body = Expression.Add(paramA, paramB);

    // Compile it
    Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();

    // Call it
    return add(a, b);
}

This way you're creating a Func<T, T, T> which performs the addition. The full explanation can be found in this article.

Adi Lester
  • 24,731
  • 12
  • 95
  • 110
13

Type T is not known by the compiler, so it cannot find an overloaded + operator defined anywhere...

The best you can currently do is declare your method as such (since all numeric types are convertible to double):

public static double Add (double number1, double number2)
{
  return number1 + number2;
}

or if you're sure a suitable + operator will be defined:

public static T Add<T>(T number1, T number2)
{
  dynamic dynamic1 = number1;
  dynamic dynamic2 = number2;
  return dynamic1 + dynamic2;
}

Updated

or a combination of the two:

public static T Add<T>(T in1, T in2)
{
    var d1 = Convert.ToDouble(in1);
    var d2 = Convert.ToDouble(in2);
    return (T)(dynamic)(d1 + d2);
}
Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
6

This is a problem that I just had when I wanted a generic method that could work on arbitrary lists of numbers, for example:

public T Calculate<T>(IEnumerable<T> numbers);

The solution I found was to use a lambda expression:

public T Calculate<T>(Func<T, T, T> add, IEnumerable<T> numbers);

Which you'd then call by

var sum = this.Calculate((a, b) => a + b, someListOfNumbers);

Obviously in some cases you may as well just have + inside the code instead of lambda expressions, but if you need to perform maths operations in a generic way this was the easiest thing I could come up with that is compile safe.

Andy C
  • 795
  • 1
  • 9
  • 10
  • Note that this function already exists - it's the LINQ Aggregate function: learn.microsoft.com/en-us/dotnet/api/…, useable as: var sum = enumerable.Aggregate((a, b) => a + b); – Rich O'Kelly Jun 10 '19 at 12:44
4

Since this is a generic type without a constraint the compiler has no knowledge if the types involved will have '+' overloaded hence the compiler error.

These are some workarounds:

public static TResult Add<T1, T2, TResult>(T1 left, T2 right, Func<T1, T2, TResult> AddMethod)
{
    return AddMethod(left, right);
}

var finalLabel = Add("something", 3,(a,b) => a + b.ToString());

Below code lets you build but it's evaluated at run time so not runtime safe

public static T AddExpression<T>(T left, T right)
{
    ParameterExpression leftOperand = Expression.Parameter(typeof(T), "left");
    ParameterExpression rightOperand = Expression.Parameter(typeof(T), "right");
    BinaryExpression body = Expression.Add(leftOperand, rightOperand);
    Expression<Func<T, T, T>> adder = Expression.Lambda<Func<T, T, T>>(
        body, leftOperand, rightOperand);
    Func<T, T, T> theDelegate = adder.Compile();
    return theDelegate(left, right);
}
Banana
  • 2,295
  • 1
  • 8
  • 25
Ira
  • 734
  • 10
  • 7
4

Try This code. This is a generic code for addition.

public static dynamic AddAllType(dynamic x, dynamic y)
{
    return  x + y;
}
  • While this works, this isn't a great idea. The point of generics to incur the type-resolving cost at compile time. With dynamic, you will incur this at run time. It can have a non-trivial performance impact. – Siddhartha Gandhi Sep 29 '21 at 20:16
3
        public class generic<T>
        {
            T result;
            public generic(T eval1, T eval2)
            {

                dynamic a = eval1;
                dynamic b = eval2;
                result = a + b;
                Console.WriteLine(result);
                Console.ReadLine();


            }

             static void Main(string[] args)
        {

             generic<int> genobj = new generic<int>(20,30);

        }
Seyed Morteza Kamali
  • 806
  • 1
  • 10
  • 22
siva
  • 31
  • 1
3

This prevents developers to write buggy code. Few questions to better explain the question:

  1. Does the compiler know the type[No, because it's a generic type].
  2. Can it accept objects as parameters [Yes, it can and because of this it won't know what to do with them --> buggy code]

Since you want to prevent your code to be buggy, C# doesn't allow you to have '+' '-' and other operators.

Solution: you can use "dynamic", "var" types and can return the summation of them if required.

KamalDeep
  • 791
  • 5
  • 8
1

If you do not want to (or cannot) use dynamic types or generate code at run-time, there is another approach I borrowed from the EqualityComparer implementation. It is a little lengthy, but another possibility utilizing "classic" .NET tools.

First, you define a generic interface which acts like a "trait", defining the addition methods you want to have:

/// <summary>
/// Represents an interface defining the addition calculation for generic types.
/// </summary>
public interface IAddition<T>
{
    /// <summary>
    /// Calculates the addition result of <paramref name="left"/> and <paramref name="right"/>.
    /// </summary>
    /// <param name="left">The left operand.</param>
    /// <param name="right">The right operand.</param>
    /// <returns>The calculation result.</returns>
    T Add(T left, T right);
}

Now, you implement this trait for the types you are interested in, in this example I do it for float:

internal class SingleAddition : IAddition<Single>
{
    Single IAddition<Single>.Add(Single left, Single right) => left + right;
}

Then you create a generic static class which will be the one you'll actually interact with. It automatically creates and caches an implementation of the IAddition<T> interface fitting its generic type:

/// <summary>
/// Represents an implementation of addition calculations for generic types.
/// </summary>
/// <typeparam name="T">The type to support the addition calculation.</typeparam>
public static class Addition<T>
{
    private static readonly IAddition<T> _implementation = Implement();

    /// <summary>
    /// Calculates the addition result of <paramref name="left"/> and <paramref name="right"/>.
    /// </summary>
    /// <param name="left">The left operand.</param>
    /// <param name="right">The right operand.</param>
    /// <returns>The calculation result.</returns>
    public static T Add(T left, T right) => _implementation.Add(left, right);

    private static IAddition<T> Implement()
    {
        Type type = typeof(T);
        // If T implements IAddition<T> return a GenericAddition<T>.
        if (typeof(IAddition<T>).IsAssignableFrom(type))
            return (IAddition<T>)Activator.CreateInstance(typeof(GenericAddition<>).MakeGenericType(type));
        // Otherwise use a default implementation for primitive types.
        switch (type.IsEnum ? Type.GetTypeCode(Enum.GetUnderlyingType(type)) : Type.GetTypeCode(type))
        {
            case TypeCode.Single:
                return (IAddition<T>)new SingleAddition();
            default:
                throw new NotSupportedException($"Type {type.Name} does not support addition.");
        }
    }
}

internal sealed class GenericAddition<T> : IAddition<T> where T : IAddition<T>
{
    T IAddition<T>.Add(T left, T right) => left.Add(left, right);
}

Of course, you'd extend the switch on type codes to support all types you're interested in. Those would be all primitive types and those you cannot modify, since you can simply implement the IAddition<T> interface for types you can modify - the GenericAddition implementation will take care of using it then.

Note that Enum values are already supported due to the check of the underlying type I added.

As you can see in the static Addition<T> class, it exposes an Add method which you'll eventually call from outside like this:

public class SomeStuff<T>
{
    public T TestAddition(T left, T right) => Addition<T>.Add(left, right);
}

// Testing in C# interactive:
> SomeStuff<float> floatStuff = new SomeStuff<float>();
> floatStuff.TestAddition(12, 24.34f)
36.34

School math has never been so easy! Maybe. Not really. It's classified.

Ray
  • 7,940
  • 7
  • 58
  • 90
  • Something about seeing (T left, T right) and generating methods cached by Type makes me think this is way too complicated. But I think the approach is fair and *way* better than using dynamic, at least for performance and purity. – user1969177 Apr 11 '21 at 18:46
  • Yeah, it's pretty bad. I hoped for C# 8 getting support for "shapes" or what they were called, to allow generics to work like template arguments in C++, simply using `operator +` if it's available, no matter the implemented interfaces. – Ray Apr 11 '21 at 20:48
1

As of dotnet 7 this can be achieved using the INumber interface

public static T Add<T> (T number1, T number2) where T : INumber<T>
{
    return number1 + number2;
}

More information can be found here: https://learn.microsoft.com/en-us/dotnet/standard/generics/math

Jorg3nws
  • 31
  • 2
0

This code will probably help definitely. This will use Linq Expression to solve the problem.

    public static class GenericAggregator<T>
    {
        static Func<T, T, T> GetAdder()
        {
            var exp1 = Expression.Parameter(typeof(T), "x");
            var exp2 = Expression.Parameter(typeof(T), "y");

            Func<T, T, T> adder;
            adder = (Func<T, T, T>)Expression
                .Lambda(Expression.Add(exp1, exp2), exp1, exp2)
                .Compile();

            return adder;
        }

        public static T Sum(List<T> items)
        {
            Func<T, T, T> adder = GetAdder();
            T result = default;

            foreach (var item in items)
            {
                result = adder(result, item);
            }
            return result;
        }

        public static T Average(List<T> items)
        {
            var sumResult = Sum(items);

            Func<T, T, T> divider;
            var exp1 = Expression.Parameter(typeof(T), "x");
            var exp2 = Expression.Parameter(typeof(T), "y");

            divider = (Func<T, T, T>)Expression
                .Lambda(Expression.Divide(exp1, exp2), exp1, exp2)
                .Compile();

            var itemsCount = (T)Convert.ChangeType(items.Count, typeof(T));

            var avgResult = divider(sumResult, itemsCount);
            return avgResult;
        }
    }

Sample Usage Code:

void Test()
{
    //For Integer
    var intNums = new List<int> {1,2,3};
    var intSumResult = GenericAggregator<int>.Sum(intNums);
    
    //For Double
    var doubleNums = new List<double> { 1.98, 2.98, 3.98 };
    var doubleResult = GenericAggregator<double>.Average(doubleNums);
}
Varun
  • 379
  • 5
  • 10
-1

If you can wrap your generic type T in some kind of 'container', you could use the following approach. I provided one method (Total) for int and double, but you can easily add other types and methods.

By the way, this is similar to how Linq defines extension methods (e.g. Sum) for IEnumerable<T>.

internal struct GenericContainer<T> {
    internal T A { get; set; }
    internal T B { get; set; }
}

/// <summary>
/// Extension methods for GenericContainer<T>
/// </summary>
internal static class GenericContainerExtensions {
    internal static int Total(this GenericContainer<int> gc) {
        return gc.A + gc.B;
    }
    internal static double Total(this GenericContainer<double> gc) {
        return gc.A + gc.B;
    }
}

class Program {
    static void Main(string[] args) {
        var gc = new GenericContainer<double>() { A = 3.3, B = 4.4 };
        Console.WriteLine($"gc.Total() = {gc.Total()}");
    }
}
Will Fred
  • 19
  • 4
-2

Because nobody answered by providing solution using object. Therefore I am adding my solution. In this you have to cast your generic values to object.

So this is the working code:

public static T Add<T>(T number1, T number2)
{
    object a = number1;
    object b = number2;
    return (T)(object)((int)a * (int)b).ToString();
}
yogihosting
  • 5,494
  • 8
  • 47
  • 80
-3

As you see from the error message operator '+' can't be applied. This is occurs because compiler knows nothing about T type. It doesn't know even is this a class or not.

VMykyt
  • 1,589
  • 12
  • 17
  • @JonH mmm.. may be you are right. I dont know how to explain in few words that C# generics is very limited in comparition to the C++ templates – VMykyt Nov 14 '11 at 14:01
  • 3
    This has nothing to do with limitations. If properly done virtually anything is possible. Your original answer was `as you see from the error message operator + cant be applied`. That isn't a good answer, I didn't downvote but that's hardly the case. – JonH Nov 14 '11 at 14:02