How to create a extension method to sum up a column of a generic constrained type in a datatable
Is something like the below possible?
public static T Sum<T>(this DataTable dt, string col开发者_运维知识库umnName)
where T : IEnumerable<decimal>, IComparable<decimal>
{
return (from c in dt.AsEnumerable()
where !c.IsNull(columnName)
select c.Field<T>(columnName)
).Sum();
}
It feels like i'm almost there, but not quite :/
Just trying to sum up either decimal or int values in a column in datatable. Currently getting a compile error, however think this is due to the incorrect generic constraint.
There is no generic IEnumerable<T>.Sum()
method; rather, there are discrete IEnumerable<decimal>.Sum()
, IEnumerable<double>.Sum()
, etc. methods (realized as extension methods in the Enumerable class). So, the type of Sum
that you call must be known at compile time.
For you, that means that you cannot make your method generic (unless you make a manual type distinction in your method). You will need to create one version for Decimal, one version for Double, etc. The version for Decimal, for example, could look like this (untested, since I don't have Visual Studio available right now):
public static decimal SumDecimal(this DataTable dt, string columnName)
{
return (from c in dt.AsEnumerable()
where !c.IsNull(columnName)
select c.Field<decimal>(columnName)
).Sum();
}
You probably want:
where T : decimal
but that does not make sense to have a generic parameter then :)
Try this:
public static decimal Sum(this DataTable dt, string columnName) {
return (
from c in dt.AsEnumerable()
where !c.IsNull(columnName)
select c[columnName]
).Sum(value => Convert.ToDecimal(value));
}
Your column type must be convertible to decimal
.
I think this is more compact, though:
public static decimal Sum(this DataTable dt, string columnName) {
return dt.AsEnumerable().
Where(row => !row.IsNull(columnName)).
Sum(row => Convert.ToDecimal(row[columnName]));
}
You can also create other versions for the other integral types supported by Sum
(double
, float
, int
, long
).
Alternatively, the DataTable
already supports this scenario:
public static T Sum<T>(this DataTable dt, string columnName) {
var sum = dt.Compute("Sum(" + columnName + ")", "");
if (sum == DBNull.Value) return default(T);
return (T)Convert.ChangeType(sum, typeof(T));
}
精彩评论