Define a Generic That Implements the + Operator

Define a generic that implements the + operator

This is a pretty commonly requested new feature for C#: the ability to specify more generic parameter constraints than the ones we already have. Operators are among the most frequently asked. However, C# does not currently support this.

Possible workarounds:

  • Pass a delegate to any method that needs to do addition. This is the most type-safe option, but of course it’s annoying if you need to call such a method often. For example:

    public class Generic<T> {
    public void DoSomething(T anItem, T anotherItem, Func<T, T, T> add) {
    // instead of
    Blah(anItem + anotherItem);
    // have to write:
    Blah(add(anItem, anotherItem));
    }
    }

    Generic<int> genInt = ...;
    // and then instead of ...
    genInt.DoSomething(1, 2);
    // have to write:
    genInt.DoSomething(1, 2, (a, b) => a + b);
  • Declare your own interface IAddable. Then you can use it as a generic type parameter constraint, but obviously you can’t use int as the parameter then. You would have to use a struct of your own that contains just an int and which implements IAddable:

    public interface IAddable<T> {
    T Add(T other);
    }
     
    public struct Integer : IAddable<Integer> {
    public int Value;
    public Integer(int value) { Value = value; }
    public Integer Add(Integer other) { return new Integer(Value + other.Value); }
    }

    // then instead of
    Generic<int> blah = ...;
    // have to write:
    Generic<Integer> blah = ...;
  • dynamic. Another possible workaround is to use dynamic, but this is rather hacky and completely unsafe: it will let you pass in any type and call any method or operator, and only crash at runtime, not at compile-time.

Is there a generic constraint I could use for the + operator?

There are no such devices in C#. A few options are available, though:

  • in C# 4.0 and .NET 4.0 (or above), use dynamic, which supports + but offers no compile time checking
  • in .NET 3.5 (or above), MiscUtil offers an Operator class which makes operators available as methods - again, without any compile-time checking

So either:

return (dynamic)left.Evaluate(context) + (dynamic)right.Evaluate(context);

or

return Operator.Add(left.Evaluate(context), right.Evaluate(context));

operator overloading with generics

The problem is the compiler cannot know if + operator can be applied to T. Unfortunately, there is no way to constraint T to be a numeric type in C#.

However, you might be able to workaround this using the dynamic runtime:

public class Complex<T> where T : struct
{
public T _a, _b;
public Complex(T i, T j)
{
_a = i;
_b = j;
}
public static Complex<T> operator +(Complex<T> i, Complex<T> j)
{
return new Complex<T>(Sum(i._a, j._a), Sum(i._b, j._b));
}

private static T Sum(T a, T b)
{
return (dynamic)a + (dynamic)b;
}
}

Can't operator == be applied to generic types in C#?

"...by default == behaves as described above for both predefined and user-defined reference types."

Type T is not necessarily a reference type, so the compiler can't make that assumption.

However, this will compile because it is more explicit:

    bool Compare<T>(T x, T y) where T : class
{
return x == y;
}

Follow up to additional question, "But, in case I'm using a reference type, would the the == operator use the predefined reference comparison, or would it use the overloaded version of the operator if a type defined one?"

I would have thought that == on the Generics would use the overloaded version, but the following test demonstrates otherwise. Interesting... I'd love to know why! If someone knows please share.

namespace TestProject
{
class Program
{
static void Main(string[] args)
{
Test a = new Test();
Test b = new Test();

Console.WriteLine("Inline:");
bool x = a == b;
Console.WriteLine("Generic:");
Compare<Test>(a, b);

}

static bool Compare<T>(T x, T y) where T : class
{
return x == y;
}
}

class Test
{
public static bool operator ==(Test a, Test b)
{
Console.WriteLine("Overloaded == called");
return a.Equals(b);
}

public static bool operator !=(Test a, Test b)
{
Console.WriteLine("Overloaded != called");
return a.Equals(b);
}
}
}

Output

Inline:
Overloaded == called

Generic:

Press any key to continue . . .

Follow Up 2

I do want to point out that changing my compare method to

    static bool Compare<T>(T x, T y) where T : Test
{
return x == y;
}

causes the overloaded == operator to be called. I guess without specifying the type (as a where), the compiler can't infer that it should use the overloaded operator... though I'd think that it would have enough information to make that decision even without specifying the type.

How to ensure type in a generic implements some operators in Dart?

I think the best you can do is just assume that the elements have these methods and leave the type parameter unbounded. That will get rid of the warnings, though it's probably a bit unsatisfying when you want the type system to help you out.

Union types would help, so here's the bug you can star: http://dartbug.com/4938

C# Generic Operators

No, you can't declare generic operators in C#.

Operators and inheritance don't really mix well.

If you want Foo + Foo to return a Foo and Bar + Bar to return a Bar, you will need to define one operator on each class. But, since operators are static, you won't get the benefits of polymorphism because which operator to call will be decided at compile-time:

Foo x = new Bar();
Foo y = new Bar();
var z = x + y; // calls Foo.operator+;


Related Topics



Leave a reply



Submit