How to get linq sum of IEnumerable<object>
Solution 1
You can use expression trees to generate the required add function, then fold over your input list:
private static Func<object, object, object> GenAddFunc(Type elementType)
{
var param1Expr = Expression.Parameter(typeof(object));
var param2Expr = Expression.Parameter(typeof(object));
var addExpr = Expression.Add(Expression.Convert(param1Expr, elementType), Expression.Convert(param2Expr, elementType));
return Expression.Lambda<Func<object, object, object>>(Expression.Convert(addExpr, typeof(object)), param1Expr, param2Expr).Compile();
}
IEnumerable<object> listValues;
Type elementType = listValues.First().GetType();
var addFunc = GenAddFunc(elementType);
object sum = listValues.Aggregate(addFunc);
note this requires the input list to be non-empty, but it has the advantage of preserving the element type in the result.
Solution 2
If you know the exact type is always going to be a numeric type, you should be able to use something like:
double total = listValues.Sum(v => Convert.ToDouble(v));
This will work because Convert.ToDouble
will look for IConvertible
, which is implemented by the core numeric types. You are forcing the type to be a double
and not the original type, as well.
Miguel
Updated on June 17, 2022Comments
-
Miguel almost 2 years
How do I get the sum of numbers that are in an IEnumerable collection of objects? I know for sure that the underlying type will always be numeric but the type is determined at runtime.
IEnumerable<object> listValues = data.Select(i => Convert.ChangeType(property.GetValue(i, null), columnType));
After that I want to be able to do the following (the following has the error:"Cannot resolve method Sum"):
var total = listValues.Sum();
Any ideas? Thank you.
-
Michael Schnerring about 11 yearsKeep in mind that this is might throw an
InvalidCastException
for e.g. strings and other objects! -
Miguel about 11 years@ebeeb - that is true, the code before that call ensures that only numeric types are getting to that point.
-
Miguel about 11 yearsReed - your solution is simple and works just fine, but I would like to preserve the original type.
-
Reed Copsey about 11 years@Mike the problem is there's no way to specify the compile time type to even set the variable properly. You could (potentially) put it in an
object
, but that won't be very useful... -
Miguel about 11 yearsyour solution works perfectly fine! just trying to understand the whole concept. Thank you.
-
Miguel about 11 yearsIn my scenario this solution only works when the underlying type is int.