Звучит так, будто вам нужен способ извлечения строкового свойства и свойства double (при условии, что «десятичное» в вашем посте было опечаткой, а не «двойным» в вашем коде) - Func
здесь уместно:
public static double SumIf<T>(this IEnumerable<T> source,
string targetText,
Func<T, string> textSelector,
Func<T, double> valueSelector)
{
double sum = 0;
foreach (T item in source)
{
if (textSelector(item) == targetText)
{
sum += valueSelector(item);
}
}
return sum;
}
(Обратите внимание, что я удалил неиспользуемый начальный параметр и сделал его методом расширения в самом списке. Неиспользование значения кажется мне немного неприятным запахом ... Я также изменил тип параметра на IEnumerable<T>
, так как вам не нужно, чтобы это был действительно список.)
Обратите внимание, что на самом деле это в основном эквивалентно:
public static double SumIf<T>(this IEnumerable<T> source,
string targetText,
Func<T, string> textSelector,
Func<T, double> valueSelector)
{
return source.Where(x => textSelector(x) == targetText)
.Sum(valueSelector);
}
Лично я бы, вероятно, использовал обычную функцию предиката вместо строки и текстового селектора:
public static double SumIf<T>(this IEnumerable<T> source,
Func<T, bool> predicate,
Func<T, double> valueSelector)
{
return source.Where(predicate)
.Sum(valueSelector);
}
Тогда вы бы позвонили с
double sum = list.SumIf(x => x.Name == "mort", x => x.Amount);
... что мне так же хорошо, как:
double sum = list.SumIf("mort", x => x.Name, x => x.Amount);
... но значительно более гибок.
Как отмечено в комментариях, вам это вообще нужно? Вы используете его в достаточном количестве мест, чтобы сделать простые вызовы Where / Sum невыносимыми? Черт возьми, вы можете превратить его в Sum
вызов, используя условный оператор:
double sum = list.Sum(x => x.Name == "mort" ? x => x.Amount : 0d);