Как создать метод расширения для суммирования столбца общего ограниченного типа в таблице данных - PullRequest
1 голос
/ 01 октября 2010

Возможно ли что-то похожее на приведенное ниже?

    public static T Sum<T>(this DataTable dt, string columnName) 
        where T : IEnumerable<decimal>, IComparable<decimal>
    {            
        return (from c in dt.AsEnumerable()
                where !c.IsNull(columnName)
                select c.Field<T>(columnName)
                ).Sum();
    }

Такое ощущение, что я почти на месте, но не совсем: /

Просто пытаюсь суммировать десятичные или целые значения встолбец в датируемой.В настоящее время получаю ошибку компиляции, однако думаю, что это связано с неправильным общим ограничением.

Ответы [ 3 ]

2 голосов
/ 01 октября 2010

Универсального метода IEnumerable<T>.Sum() не существует; скорее существуют дискретные IEnumerable<decimal>.Sum(), IEnumerable<double>.Sum() и т. д. методы (реализованные как методы расширения в классе Enumerable ). Итак, тип Sum, который вы называете , должен быть известен во время компиляции .

Для вас это означает, что вы не можете сделать свой метод универсальным (если вы не сделаете ручное различие типов в своем методе). Вам нужно будет создать одну версию для Decimal, одну версию для Double и т. Д. Например, версия для Decimal может выглядеть следующим образом (не проверено, поскольку у меня сейчас нет Visual Studio):

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();
}
1 голос
/ 01 октября 2010

Вы, вероятно, хотите:

where T : decimal

но тогда нет смысла иметь общий параметр:)

0 голосов
/ 01 октября 2010

Попробуйте:

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

Ваш тип столбца должен быть конвертируемым в decimal.

Я думаю, что это более компактно:

public static decimal Sum(this DataTable dt, string columnName) {
  return dt.AsEnumerable().
    Where(row => !row.IsNull(columnName)).
    Sum(row => Convert.ToDecimal(row[columnName]));
}

Вы также можете создавать другие версии для других целочисленных типов, поддерживаемых Sum (double, float, int, long).

Кроме того, DataTable уже поддерживает этот сценарий :

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));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...