tags:

views:

607

answers:

4

I have a method that accepts an IEnumerable-decimals and performance various math functions. I want to use the same method on an IEnumerable-int-. How do I implement this? For example to find a simple sum?

void Calculate<T>(IEnumerable <T> ListOFNumbers)
{
   int count= ListofNumbers.Count();
   ?sum=?;
}
A: 

You can use the IEnumerable.Sum function

Jeremy
That doesn't work with generics.
Marc Gravell
A: 

This is purely looking and jumping around in reflector.


{
   IQueryable qt = ListofNumbers.AsQueryable();
   Console.WriteLine(qt.Sum());
}
shahkalpesh
That doesn't work with generics.
Marc Gravell
A: 

You can use the built-in LINQ Aggregate(...) method to do this and many other more complicated calculations i.e.

int[] n = new int[] { 1, 2, 3, 4, 4, 5, 5, 6 };
int sum = n.Aggregate((x, y) => x + y);

as the lamdba is executed, once for each element in the enumeration the values of x,y are

0,1
1,2
3,3
6,4,
10,4,
14,5,
19,5
24,6

respectively and the final result is 30

With this you can use any aggregating function you want:

For example:

int[] n = new int[] { 1, 2, 3, 4, 4, 5, 5, 6 };
int count = n.Aggregate((x, y) => x + 1);

To simplify this there are built-in functions for common aggregates like Count and Max. Hope this helps

Alex

Alex James
That doesn't work for generics.
Marc Gravell
What do you mean it doesn't work with generics?The Aggregate method is a generic, and the action you pass in can do anything you want, so if can work with any type, so yeah t + t won't work for every T but you can do anything in the action so why does that matter?
Alex James
The question starts with "IEnumerable <T> ListOFNumbers". Given that *and just that*, try to use Aggregate to do a sum. You can't, because operators (+ etc) aren't supported for C# generics. At all.
Marc Gravell
Okay I see where you are coming from. I was just asserting that if you needed special operators you could implement them in the lambda you pass to the aggregate method.
Alex James
+2  A: 

This is all freely available in MiscUtil. The Operator class provides access to generic arithmetic; and there are generic implementations (as extension methods) of Sum, Average, etc - and works with any type with suitable operators in addition to the primitives. So for example, you could use Sum with of Complex<T>, etc.

Note that it currently uses .NET 3.5; I did have a 2.0 version somewhere, but it isn't as tested....

A simplified example of sum is shown in the usage document:

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

Although IIRC the actual implementation has a bit more...

As an aside, note that dynamic (in .NET 4.0 / C# 4.0) supposedly supports operators, but we'll have to wait for the beta to see what it does. From my previous looks at dynamic in the CTP, I expect it to be a bit slower than the MiscUtil code, but we shall see.

Marc Gravell
how much slower would this be than non-generic?
zsharp
I don't have metrics to hand - but it wasn't much slower at all. The `foreach` is still by far the dominant factor.
Marc Gravell
How the generic arithmetics offered by MiscUtil works internally?
Alex Yakunin
It uses Expression (.NET 3.5) to build the operators, compiles them to delegates, and caches them. I did have a 2.0 version kicking around somewhere. A *simplified* example of how it is implemented is shown here: http://www.yoda.arachsys.com/csharp/genericoperators.html
Marc Gravell
I've asked because we have similar framework: http://help.dataobjects.net/##DataObjects.Net_4-Essentials.chm/html/N_Xtensive_Core_Arithmetic.htm
Alex Yakunin
It's implemented differently (it uses our AssociateProvider to get some associate logic related to the particular type), but the result must be the same from the point of performance of a single operation.
Alex Yakunin