tags:

views:

73

answers:

2

Hi,

When performing OO design, is it better to consolidate a collection of methods that use simple value types into a generic method ? For example:

public int Sum(int x, int y)

// Overload with float.
public float Sum(float x, float y)

Consolidated to:

public T Sum<T> (T x, T y)

Thanks,

Scott

+3  A: 

In general yes, however, specifically with your example (summing two arguments) - you can't do it with generics, since the + operator is not part of any interface to which you can constrain your generic type argument :)

(Note: this is my C# part talking, in other languages that might still be possible)

Aviad P.
Thanks for your answer! Is it not possible to do this or is it a bad design decision ? I am thinking with the way it's written now that both parameters are unconstrained, so someone could pass any object in and the + operation is not overloaded for all types so it would break. Does this sound right ?
Scott Davies
Yes, a missing piece to the CLR - is an interface `INumeric` that would include those operators, (Applied to all the core types that implement them - int, uint, float, decimal, etc.)
Charles Bretana
@Scott Davies - No, it would not be possible (read - compile error), the compiler doesn't know how to translate the call to '+' for an unconstrained type. If the type is unconstrained, this is the case for any method, not just '+'.
Aviad P.
No, it would not work as is, because as soon as you use the + operator inside this generic function, the compiler will complain because since you have not constrained the T type, it knows that not every type can use the + operator...
Charles Bretana
Ah, ok. A compile time fault is good, then, as it stops this. Thanks!
Scott Davies
+2  A: 

In some cases, yes (not always); and despite rumour to the contrary, it is possible. I wrote some code for "MiscUtil" (free, etc) that does exactly this, and which works for all types with suitable operators (even your own structs and classes, or Nullable<T>, etc).

The problem here is that there is no interface that supports Add etc, so until dynamic comes along (in 4.0) it is tricky to do; but it can be done - here's the usage page, with a simiplfied Sum (the actual code in "MiscUtil" is slightly more complex):

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;
}

Again, a lot of this is relatively simple in 4.0 with dynamic, since this supports operators; however, last time I benchmarked it, dynamic was slower than my (ab)use of Expression.

As an aside, the reason that standard LINQ can provide a Min / Max is because of IComparable/IComparable<T>, assisted by Comparer<T>.Default.

Marc Gravell