views:

421

answers:

7

I want to write a C# method that can accept any number. Something like:

public static T Sum(T a, T b) where T : number {  // (not real code)
    return a + b;
}

But I don't see a "number" base class in C#, as exists in most other languages I've used. The numeric value types are IComparable, IFormattable, IConvertible, IComparable, and IEquatable, but nothing that seems to have any arithmetic capabilities. They're all structs, with no apparent common superclass, apart from object. (Forgive me if I'm screwing up the meaning here, since I'm not too familiar with C# structs and precisely all the ways they are like or unlike classes.)

Am I missing something, or is it not possible to write a method in C# that does "a + b" without declaring exactly what a and b are in the context of the "+"?

+1  A: 

Unfortunately, no such class/interface exists.

C. Ross
A: 

The best you can do is where T : struct which requires a ValueType; all numerics are ValueTypes.

Unfortunately, so are all user-defined structs, so that's the drawback. There's no specific generic that will accept all numeric classes.

I hesitate to even suggest this, but you might consider runtime checks against the type of T in the method and throw if T is not an int, long, short, float, or double. Unfortunately, this will not help a programmer at compile-time.

Randolpho
+3  A: 

You will have to resort to using overloading. A little like the Math class is doing with function like Math.Max where it support all numeric types.

The link proposed by CD is also resourceful.

Pierre-Alain Vigeant
Or like the Linq extension methods are doing with IEnumerable.Sum and implement only half the numeric types!
Ken
Not necessarily. There are generic-based solutions (see my answer for more).
Marc Gravell
+1  A: 

int and the other numeric types are ValueTypes. As already said, all you can do is saying where T: struct. Well, you could use reflection to check if the type argument implements addition... but i'm not sure if that's a good idea.

Botz3000
+3  A: 

See this SO question for similar discussion.

Also, you can do this (with some tedious effort) if you're willing to create separate Types for each of the .Net core number types you want to use it for...

Create two structs, called say, MyInt, and MyDecimal which act as facades to the CTS Int32, and Decimal core types (They contain an internal field of that respective type.) Each should have a ctor that takes an instance of the Core CTS type as input parameter..

Make each one implement an empty interface called INumeric

Then, in your generic methods, make the constraint based upon this interface. Downside, everywhere you want to use these methods you have to construct an instance of the appropriate custom type instead of the Core CTS type, and pass the custom type to the method.

NOTE: coding the custom structs to properly emulate all the behavior of the core CTS types is the tedious part... You have to implement several built-in CLR interfaces (IComparable, etc.) and overload all the arithmetic, and boolean operators...

Charles Bretana
+1  A: 

Check this one: Generics - where T is a number?

CD
A: 

This is a very common question; if you are using .NET 3.5, there is a lot of support for this in MiscUtil, via the Operator class, which supports inbuilt types and any custom types with operators (including "lifted" operators); in particular, this allows use with generics, for example:

public static T Sum<T>(this IEnumerable<T> source) {
    T sum = Operator<T>.Zero;
    foreach (T value in source) {
        if (value != null) {
            sum = Operator.Add(sum, value);
        }
    }
    return sum;
}

Or for another example; Complex<T>

Marc Gravell
It's kind of neat (or gross) that there's a library to do all the overloading and casting for me, but I don't consider "Operator.Add(a,b)" to be a solution to the problem of "a+b" not being generic. If I want to become generic by writing a bunch of verbose code, I don't need a third-party library to do that. :-)
Ken
There *is* no overloading nor casting. It is genuine generic-based code, with some clever use of Expression to pre-compile a delegate (per-type) that can do the arithmetic.
Marc Gravell
It might help if I clarify that `Add` is actually a generic method (`Add<T>`); simply that in the example we're using generic-type-inference to avoid having to add the `<T>` ourselves. But it is still there.
Marc Gravell
OK, I misspoke w.r.t. the approach MiscUtil uses, but I still don't consider Operator.Add(a,b) a solution. :-)
Ken