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 int
s, long
s, single
s or double
s.
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 int
s 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 short
s is a short
itself.
It is even reflected in the fact that you have to do explicit casting when adding short
s:
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 short
s to int
s:
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);
精彩评论