开发者

LINQ aggregate functions on bytes, shorts, and unsigned values

How would you go about using LINQ aggregate functions (ex. Sum, Average) on collections of bytes, shorts, and unsigned values? Granted, I'm a new C# programmer, but I can't even figure out how to get something that compiles let alone has proper output.

H开发者_开发百科ere's a trivial example of what I am trying to do:

short[] numbersArray = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
short sumArray = numbersArray.Sum();

or

List<short> numbersList = new List<short> { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
short sumList = numbersList.Sum();

I can't either of these samples to work. If I change the data type to int it works, but I can't get it to work for shorts, bytes, uints, etc.

What am I doing wrong?


Enumerable.Sum<T>() is only defined for IEnumerable<T> where T in

double,
double?
int,
int?
decimal,
decimal?
long,
long?
float,
float?

This is because there is no addition operator* for short or any of the other primitive types (short + short is int, for example).

You have to say:

short[] numbersArray = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int sumArray = numbersArray.Sum(x => (int)x);

and less explicitly you can get away with

short[] numbersArray = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int sumArray = numbersArray.Sum(x => x);

In this case, you are now invoking the overload:

int Enumerable.Sum<short>(
    this IEnumerable<short> source,
    Func<short, int> selector
)

*: Here I mean "operator" in the sense of an function F:(short x short) -> short.


Enumerable.Sum accepts either ints, longs, singles or doubles.

You can cast the numbers to make them eligible as the parameter:

short [] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int sum = numbers.Cast<int> ().Sum ();

As an alternative, you can provide a Func<TSource, int> lambda that selects ints for you:

short [] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int sum = numbers.Sum (x => x); // lambda type is inferred as Func<short, int>

I declare sum as int because it's really unsafe to think a sum of shorts is a short itself.
It is even reflected in the fact that you have to do explicit casting when adding shorts:

int sum = a + b; 
short shortSum = (short)(a + b); // you can use an explicit casting to get short

So if you're certain you're not going to overflow, just cast the result:

short shortSum = (short) numbers.Cast<int> ().Sum ();


The Sum extension method doesn't have an overload that takes an IEnumerable<short>.

Instead, you can pass a lambda expression that implicitly converts the shorts to ints:

short sumList = (short)numbersList.Sum(i=>i);


This confused me, but I was able to make it work like:

List<short> li = new List<short> {1,2,3,4,5};
short l = (short)li.Sum(i => i);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜