33

is there some 'where' type contraints in can add to make the follwing code compile ?

public class Plus<T> : BinaryOperator<T> where T : ...
{
    public override T Evaluate(IContext<T> context)
    {
        return left.Evaluate(context) + right.Evaluate(context);
    }
}

Thanks :)

Camilo Martin
  • 35,841
  • 20
  • 107
  • 152
  • 4
    Actually, you can't. See here: http://stackoverflow.com/questions/147646/solution-for-overloaded-operator-constraint-in-net-generics – dlev May 13 '11 at 20:01
  • 2
    This is a frequently requested feature but it does not exist today; there's no way to genericize over the existence of a *static* method, and overloaded operators are always static. – Eric Lippert May 13 '11 at 20:37
  • To add to eric's statement go down the rabbit hole, operators don't have to just take T, they don't even have to return it! As such, despite really wanting it, I'd be happy to wait for it to be done right... – ShuggyCoUk May 15 '11 at 13:27
  • Possible duplicate of [Solution for overloaded operator constraint in .NET generics](https://stackoverflow.com/questions/147646/solution-for-overloaded-operator-constraint-in-net-generics) – Wai Ha Lee Nov 14 '19 at 08:33

4 Answers4

24

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

So either:

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

or

return Operator.Add(left.Evaluate(context), right.Evaluate(context));
Camilo Martin
  • 35,841
  • 20
  • 107
  • 152
Marc Gravell
  • 976,458
  • 251
  • 2,474
  • 2,830
5

The Type parameter constraints in C# are very limited and is listed here. So the answer is no as far as compile time check goes. If T is a type that you create and manage, one way to go about it would be to

interface IAddable 
{
   IAddable Add(IAddable foo);
}

and implement IFoo for all your types and use where T: IAddable as constraint and use Add() instead of +

Bala R
  • 104,615
  • 23
  • 192
  • 207
1

Using a generic constraints you can force T

  • to be a reference type or a value type
  • to inherit from a certain class
  • to implement certain interface
  • to have parameterless constructor

But that's all. You can't force the existence of the static operator+ on it.

svick
  • 225,720
  • 49
  • 378
  • 501
1

With C# 8 default interface methods you can achieve something similar, but it might not solve your exact use case:

You can define an interface with a default implementation of an operator:

public interface IFoo
{
    double Value { get; }

    public static IFoo operator +(IFoo a, IFoo b)
    {
        return new Foo(a.Value + b.Value);
    }
}

public class Foo : IFoo
{
    public double Value { get; }

    public Foo(double value)
    {
        Value = value;
    }
}

And consume it in a generic method/class like this:

public static class Program
{
    public static void Main()
    {
        var f1 = new Foo(1);
        var f2 = new Foo(2);
        var sum = Add(f1, f2);
        Console.WriteLine(sum.Value);
    }

    public static IFoo Add<T>(T a, T b) where T : IFoo
    {
        return a + b;
    }
}
tomfroehle
  • 482
  • 4
  • 15