需求說明
給定一個 DataTable,如果從中取出數值類型列的值並對其累加?
限制:不知該列是何種數值類型。
解決方案
1、將表轉換為 IEnumerable<dynamic>
,而后獲取指定的列的值並對其累加;
2、如果該值類型為 DBNull
,則視作 0;
3、使用 double,確保最小程度丟失精度。
關鍵方法 AsDynamicEnumerable
該方法出自 http://codego.net/368045/ ,關鍵方法為:
public static class DynamicTable
{
public static IEnumerable<dynamic> AsDynamicEnumerable(this DataTable table)
{
//table.CheckNull("table");
return table.AsEnumerable().Select(row => new DynamicRow(row));
}
private sealed class DynamicRow : DynamicObject
{
private readonly DataRow _row;
internal DynamicRow(DataRow row) { _row = row; }
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var retVal = _row.Table.Columns.Contains(binder.Name);
result = retVal ? _row[binder.Name] : null;
return retVal;
}
}
}
使用與單元測試
緣何選擇 Double?
從 int、uint、long 或 ulong 轉換為 float,從 long 或 ulong 轉換為 double 會丟失精度(loss of precision),但不會導致數量級的丟失(loss of magnitude)。其它的隱式數制轉換不會丟失任何信息。
——《C# Language Specification 5.0 (翻譯)第六章 轉換》,「隱式數值轉換」,本文作者譯
需要改進之處
事實上這個方法並非健全之策。如果你對數值的精度要求比較高,或者你選擇使用 Decimal
類型,則其可能丟失的精度會讓你不可容忍。另外,還需要判斷該列對象是否為數值類型的值,如果不是的話該如何處理。最后,同時也最關鍵的是,如果不用DataTable,那么就沒有這些煩惱了。