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);
精彩评论