3

I am trying to achieve something similar to the following code snippet.

enter image description here

As the red line indicates Math.Min for IComparable<T> does not seem to work. I need to use Math.Min or Math.Max for this generic class. The T is going to be either int or double or decimal type.

How could I easily solve this?

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
DynamicScope
  • 695
  • 9
  • 26

3 Answers3

3

Write your own generic Max and Min

public static T Max<T>(T x, T y)
{
    return (Comparer<T>.Default.Compare(x, y) > 0) ? x : y;
}
PraveenVenu
  • 8,217
  • 4
  • 30
  • 39
2

There is no general solution for arithmetic operations. But for simple comparisons, you can trivially implement it yourself:

T Min<T>(T x1, T x2) where T:IComparable<T>
{
  int comp=x1.CompareTo(x2);
  if(comp<=0)
    return x1;
  else
    return x2;
}

But I generally avoid the IComparable<T> constraint, and rather ask the user to pass in IComparer<T> as parameter to the constructor, and default to Comparer<T>.Default if he doesn't specify one.

This technique allows using the class even on types that don't implement IComparable<T>, provided the user passes in an alternative implementation.

class Foo<T>
{
  readonly IComparer<T> _comparer;

  public Foo()
    :this(Comparer<T>.Default)
  {
  }

  public Foo(IComparer<T> comparer)
  {
    _comparer=comparer;
  }

  T Min(T x1, T x2)
  {
    int comp = _comparer.Compare(x1,x2);
    if(comp <= 0)
      return x1;
    else
      return x2;
  }
}
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
0

Ok, so it's going to be an int, decimal or double, so the ugly hack is to do something like

if not null
   if(decimal.tryparse(val.ToString(), out aDecimal))
      and if the other value can be made into a decimal
          return math.max or min or what ever.

I'm already regretting using pseudo code...

Depending on what numerical types you include you just use the largest of them for the check above.

Be careful though as soon as someone says, "Hey this class is generic, lets use it with a class that wraps a decimal" you end up in a world of pain and then it's time to look at some of the other options posted here.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Ian
  • 4,885
  • 4
  • 43
  • 65
  • You'd need a conditional tweak for the assignment to the 2d array at the end as well depending on the type. Investigate the Convert class. That will help. – Ian Jul 25 '12 at 06:54
  • Your code only fails for some values of `double`, since `double` allows a different set of values (in particular large finite values, NaN and infinities). – CodesInChaos Jul 25 '12 at 06:55
  • Totally agree, but for most applications NaN and infinity aren't issues. I was trying to give an example which met his original brief. I work in the financial domain mainly. I'm sure our quants are working on a way to trade NaN, thus delivering an infinite profit and winning. Until then though we cope with real numbers :) – Ian Jul 28 '12 at 05:50