7

Possible Duplicate:
Generics - where T is a number?

I have created a generic method for maximum and I use IComparable interface

Does anybody know how can I create a generic method for Sum? Which interface is useful in this method?

Here is my code for GetMax:

public static T GetMax<T>(T[] array) where T : IComparable
    {
        T min = array[0];

        foreach (T item in array)
        {
            if (min.CompareTo(item) < 0)
            {
                min = item;
            }
        }
        return min;
    }
Community
  • 1
  • 1

3 Answers3

8

this operation already exists Linq.Sum()

var sum = new List<int>{1,2,3}.Sum();
burning_LEGION
  • 13,246
  • 8
  • 40
  • 52
  • Only other thing to add is you have to add "using System.Linq;" at the top of your class. – nerdybeardo Jan 26 '13 at 21:26
  • 5
    Note that LINQ provides multiple overloads of `Sum` for different types. If you have an IEnumerable and don't know T (because the method is generic), then you can't use this method. – dtb Jan 26 '13 at 21:30
  • But how would you describe the behaviour of complex objects here? – SohamC Aug 26 '21 at 06:38
3

No, you can't create one generic method for all types. But you can use LINQ extension method Sum for some types: decimal, double, int, long, ... See more types here: Enumerable.Sum.

int[] array1 = { 1, 3, 5, 7 };
int sum1 = array1.Sum();

For your own types you can create and implement interface ISummable:

interface ISummable<T>
{
   T Add(T a, T b);
}

Then your generic method will be similar to this one:

T Sum<T>(T a, T b) where T:ISummable<T>
{
    return a.Add(a,b);
}

See more information here: Making generics add up.

algreat
  • 8,592
  • 5
  • 41
  • 54
2

I assume you want to write a generic method Sum like this:

static T Sum<T>(this IEnumerable<T> values) where T : ??
{
    T result = 0;
    foreach (var value in values)
    {
        result = result + value;
    }
    return result;
}

Unfortunately there is no constraint that you could put in place of ?? to make this work.

The data types built into .NET implement certain interfaces. For example, int implements IComparable, IFormattable, IConvertible, IComparable<int>, and IEquatable<int>. None of these provide an Add method (or + operator) that would allow you to implement a Sum method. And you cannot add interface implementation to existing types.

What you can do, is pass a an object to the Sum method that knows how to add two values of the generic type:

static T Sum<T>(this IEnumerable<T> values, IAdder<T> adder)
{
    T result = adder.Zero;
    foreach (var value in values)
    {
        result = adder.Add(result, value);
    }
    return result;
}

with

interface IAdder<T>
{
    T Zero { get; }

    T Add(T a, T b);
}

and

class Int32Adder : IAdder<Int32>
{
    public static readonly Instance = new Int32Adder();

    public int Zero { get { return 0; } }

    public int Add(int a, int b) { return a + b; }
}
dtb
  • 213,145
  • 36
  • 401
  • 431
  • your solution has potential bug - class without zero-state will be miscalculation wrong, realization have to be ugly, with switch condition – burning_LEGION Jan 26 '13 at 21:53
  • if (values.Count == 0) throw new ArgumentException(); var result = values.GetValue(); for (var i = 1; i < values.Count; i++) { result = adder.Add(result, values[i]); } return result; //need add GetValue to interface, Linq.First() is not pass – burning_LEGION Jan 26 '13 at 22:00