4

I would like to create generic function Math.Abs() but i don't know how to make this. if i create a class Math i can't create method Abs for T value because i don't know the type of T.

If someone know how to do this ?

Thanks

Econus
  • 43
  • 6
  • I don't know C# generics that well, but in C++ at least; you can create generic function which assumes a type has operators overloaded, and if te type does not, then an exception will be thrown at compile time. – Richard J. Ross III Aug 05 '12 at 17:56
  • I would follow this pattern: http://stackoverflow.com/questions/63694/creating-a-math-library-using-generics-in-c-sharp – Chris Gessler Aug 05 '12 at 17:56
  • @RichardJ.RossIII: Notice that in C# you can't ensure that a method has operators overloaded (they are static methods, I hate this c# behaviour). That being said, you can't really "understand" if an object is a number with a generic clause. – Francesco Belladonna Aug 05 '12 at 17:58
  • @RichardJ.RossIII - C# generics do not operate in this way. You can constrain a generic type, but the constraints are rather wide in scope. – Oded Aug 05 '12 at 17:58
  • possible duplicate of [C# generic constraint for only integers](http://stackoverflow.com/questions/32664/c-sharp-generic-constraint-for-only-integers) – nawfal Apr 03 '13 at 00:06

5 Answers5

11

Six options:

  • Use reflection based on the execution-time type of T
  • Use an overload for each type you care about
  • Use if/else for every type you care about
  • Create a Dictionary<Type, Func<object, object>> containing a delegate for every type you care about
  • Use dynamic in .NET 4:

    public T Foo<T>(T value)
    {
        dynamic d = value;
        return Math.Abs(d);
    }
    
  • Use something like Marc Gravell's generic operators part of MiscUtil

I'd probably go for the overload option if possible. It will constrain you appropriately at compile-time, and avoid any potentially time-consuming boxing/reflection.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

You can't do this with generics - there are no generic type constraints that will ensure that the passed in type is a numeric type.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
2

I think it's simply illogical write a generic method for essentially something that behaves differently. Floats and doubles works in a similar way, but int doesn't work in that way (they don't have a decimal part).

Write an overload for each method should be the correct way to handle this, otherwise you'll end up doing bunch of if typeof which is basically wrong.

Francesco Belladonna
  • 11,361
  • 12
  • 77
  • 147
2

You can take type of T by T.GetType(). But it will not help you. You can't write generic method but can write Abs method for object:

private static object Abs(object num)
{
    var type = num.GetType();
    if (type == typeof(Int32))
    {
        return Math.Abs((int) num);
    }
    if (type == typeof(Int64))
        return Math.Abs((long)num);
    if (type == typeof(Int16))
        return Math.Abs((short)num);
    if (type == typeof(float))
        return Math.Abs((float)num);
    if (type == typeof(double))
        return Math.Abs((double)num);
    if (type == typeof(decimal))
        return Math.Abs((decimal)num);
    throw new ArgumentException(string.Format("Abs is not defined for type {0}", type.FullName));
}
Kirill Bestemyanov
  • 11,946
  • 2
  • 24
  • 38
0

One thing you can do is just request the Abs function:

T someGenericFunction<T>(
   T value1,
   T value2,
   Func<T, T> absFunction
) {
   ...
   var abs1 = absFunction(value1);
   ...
}

...

var decimalResult = someGenericFunction<decimal>(1.2m, -2.3m, Math.Abs);
var intResult = someGenericFunction<int>(5, 7, Math.Abs);
//etc.

// also allows you to use other kinds of abs function
var customResult = someGenericFunction<CustomType>(value1, value2, CustomType.Abs);
Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80