views:

1864

answers:

2

What would I do if I want to have a generic method that only accepts types that have overloaded an operator, for instance the subtraction operator. I tried using an interface as a constraint but interfaces can't have operator overloading.

What is the best way to achieve this?

+1  A: 

As you have found, it is simply not possible to define a static method on an interface, so you cannot use it as a constraint for your generic method.

Here is a somewhat complex workaround: http://www.codeproject.com/KB/cs/genericnumerics.aspx

If you are using .NET 3.5, this can also be accomplished via LINQ expression trees, as follows: http://rogeralsing.com/2008/02/27/linq-expressions-calculating-with-generics/

Ben Hoffstein
Note that in Roger's blog we discuss/contrast the two implementations (they are very similar) - with the conclusion that the MiscUtil code (linked previously) is more developed. But they use the same fundamental approach.
Marc Gravell
+13  A: 

There is no immediate answer; operators are static, and cannot be expressed in constraints - and the existing primatives don't implement any specific interface (contrast to IComparable[<T>] which can be used to emulate greater-than / less-than).

However; if you just want it to work, then in .NET 3.5 there are some options...

I have put together a library here that allows efficient and simple access to operators with generics - such as:

T result = Operator.Add(first, second); // implicit <T>; here

It can be downloaded as part of MiscUtil

Additionally, in C# 4.0, this becomes possible via dynamic:

static T Add<T>(T x, T y) {
    dynamic dx = x, dy = y;
    return dx + dy;
}

I also had (at one point) a .NET 2.0 version, but that is less tested. The other option is to create an interface such as

interface ICalc<T>
{
    T Add(T,T)() 
    T Subtract(T,T)()
}

etc, but then you need to pass an ICalc<T>; through all the methods, which gets messy.

Marc Gravell
I like the ability to use dynamic in .NET 4.0, it sure makes things much easier. However, it's worth pointing out that there will be a performance implication on using it because it has to do more work at runtime. I'd be interested to know how much of an impact it has, it needs some benchmarking I think.
Martin Sherburn
Benchmark already done; try the code from here: http://social.msdn.microsoft.com/Forums/en-US/vs2010ctpvbcs/thread/287db1b9-c135-40bc-a1c5-a8a51efbfc65
Marc Gravell
I tried out your library (for .NET 3.5), and I have a question: why doesn't the following line work: MiscUtil.Operator.Add("A", "B");.In my understanding, it should return "AB".
Malki
@Malki - well, we *could* add that, but that isn't really an arithmetic operation. And strictly speaking it isn't really a defined operator - it is currently the **compiler** (not the type itself) that provides that meaning of `+` for strings...
Marc Gravell