如何获得IEnumerable <object> </object>的linq和

时间:2013-03-14 18:42:37

标签: c# .net generics reflection

如何获取IEnumerable对象集合中的数字总和?我确信底层类型将始终为数字,但类型是在运行时确定的。

IEnumerable<object> listValues = data.Select(i => Convert.ChangeType(property.GetValue(i, null), columnType));

之后我希望能够执行以下操作(以下是错误:“无法解析方法总和”):

var total = listValues.Sum();

有什么想法吗?谢谢。

5 个答案:

答案 0 :(得分:11)

如果你知道确切的类型总是一个数字类型,你应该可以使用类似的东西:

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

这将有效,因为Convert.ToDouble会查找IConvertible,这是由核心数字类型实现的。您强制类型为double,而不是原始类型。

答案 1 :(得分:4)

您可以使用表达式树生成所需的添加功能,然后折叠输入列表:

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);

请注意,这需要输入列表非空,但它具有在结果中保留元素类型的优点。

答案 2 :(得分:0)

转换为一种类型。比方说,小数。

  

data.Select(i =&gt; Convert.ToDecimal(property.GetValue(i,null))。Sum();

答案 3 :(得分:0)

你可以使用动态,完美的作品:

    listValues.Sum(x => (dynamic)x);

答案 4 :(得分:-1)

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()那样抛出异常,即使你返回布尔值和对象。