如何获取IEnumerable对象集合中的数字总和?我确信底层类型将始终为数字,但类型是在运行时确定的。
IEnumerable<object> listValues = data.Select(i => Convert.ChangeType(property.GetValue(i, null), columnType));
之后我希望能够执行以下操作(以下是错误:“无法解析方法总和”):
var total = listValues.Sum();
有什么想法吗?谢谢。
答案 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()
那样抛出异常,即使你返回布尔值和对象。