我需要为List(T)编写一个通用扩展方法,它有条件地考虑T的每个字符串属性,然后在满足条件时对T的相应小数属性求和。到目前为止我的努力:
// foreach(p in Persons) { if(p.Name == "mort"){sum p.Amount;} }
public static double SumIf<T>(this T o, List<T> ListItems,
string targetStr, ?strVals?, ?dblVals?)
{
double sum = 0;
foreach(T item in ListItems)
{
if(item.?strVal? == targetStr){ sum += item.?dblVal? ; }
}
return sum;
}
感谢任何指导, MORT
答案 0 :(得分:4)
听起来你想要一种提取字符串属性和双重属性的方法(假设帖子中的“十进制”是拼写错误而不是代码中的“双精度”) - 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);
答案 1 :(得分:0)
您为方法引入了一些非常具体的约束,使得它不能是通用的,例如: T必须有财产金额。最好将这些依赖项作为函数传递:
public static double SumIf<T>(this IList<T> source,
Func<T, bool> pred,
Func<T, double> val)
{
double sum = 0;
foreach (var item in source)
if (pred(item))
sum += val(item);
return sum;
}
然后你可以将你的谓词和sum属性选择器作为lambdas传递:
List<Person> people = new List<Person>();
people.Add(new Person() { Name = "Joe", Amount =20.2});
people.Add(new Person() { Name = "Fred", Amount = 11 });
people.Add(new Person() { Name = "Joe", Amount = 5.7 });
double sum = people.SumIf(x => x.Name == "Joe", x => x.Amount);