How to get linq sum IEnumerable <object>

How to get the sum of the numbers that are in the IEnumerable object collection? I know for sure that the base 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 an error: "Unable to resolve the Sum method"):

var total = listValues.Sum();

Any ideas? Thank.

+5
source share
5 answers

You can use expression trees to generate the required add function, and then collapse your 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);

Please note: this requires the input list to be non-empty, but has the advantage of retaining the item type as a result.

+4

, , - :

double total = listValues.Sum(v => Convert.ToDouble(v));

, Convert.ToDouble IConvertible, . double, .

+10

. , .

data.Select(i = > Convert.ToDecimal( .GetValue(i, null)). Sum();

0

dyanmic, :

    listValues.Sum(x => (dynamic)x);
0
static void Main(string[] args)
{
    var sum = GetData().TryCast<double>.Sum();
}

private static IEnumerable<object> GetData()
{
    yield return 4.478;
    yield return 4f;
    yield return 0xFF;
    yield return false;
    yield return new List<string> { "foo", "bar" };
}

// the extension function
public static IEnumerable<T> TryCast<T>(this IEnumerable<object> values)
{
    foreach (var v in values)
    {
        T a = default(T);
        try
        {
            a = (T) Convert.ChangeType(v, typeof (T));
        }
        catch (FormatException)
        {
        }
        yield return a;
    }
}  

, . LINQ (!) , Convert.ToDouble() , .

-1

All Articles