我有以下代码,我想将其放入一个函数中,因此我不需要为if-block的每个案例多次复制/粘贴它:
if (sort == ExportSortOrder.CardType)
{
cards = cards.OrderBy(f => f.CardType);
foreach (CardTypes type in Enum.GetValues(typeof(CardTypes)))
{
if (!cards.Any(f => f.CardType == type))
continue;
builder.Append(type.ToString() + ": ");
builder.Append(cards.Where(f => f.CardType== type).Sum(f => f.AmountInDeck));
builder.Append(Environment.NewLine);
foreach (CardViewModel card in cards.Where(f => f.CardType == type))
{
builder.Append(card.AmountInDeck.ToString() + "\t" + card.Name.Name + Environment.NewLine);
}
builder.Append(Environment.NewLine);
}
}
else if ( //same code block as above, for a different property of CardViewModel
用于排序"卡片的属性的类型T" by始终是Enum。 到目前为止,我有以下方法可以调用:
private void AddSections<T>(IEnumerable<CardViewModel> cards, StringBuilder builder, Func<CardViewModel, T> order, Func<CardViewModel, bool> predicate)
{
cards = cards.OrderBy(order);
foreach (T value in Enum.GetValues(typeof(T)))
{
if (!cards.Any(predicate))
continue;
builder.Append(value.ToString() + ": ");
builder.Append(cards.Where(predicate).Sum(f => f.AmountInDeck));
builder.Append(Environment.NewLine);
foreach (CardViewModel card in cards.Where(predicate))
{
builder.Append(card.AmountInDeck.ToString() + "\t" + card.Name.Name + Environment.NewLine);
}
builder.Append(Environment.NewLine);
}
}
但是,现在我遇到了如何构建AddSections<T>()
的最后一个参数的问题,这是用于过滤的谓词,因为我需要为外循环的每次运行使用不同的谓词。我无法将其作为固定参数传递,因为我显然无法引用&#34;值&#34;在外部的foreach循环中。所以我认为我必须在AddSections函数内动态构建它。如果是这种情况,我该怎么做,或者我完全走错了轨道?
答案 0 :(得分:3)
这里的诀窍是用Func<CardViewModel, bool> predicate
替换Func<T, Func<CardViewModel, bool>> predicateFactory
。
我认为这就是诀窍:
private void AddSections<T>(
IEnumerable<CardViewModel> cards,
StringBuilder builder,
Func<CardViewModel, T> order,
Func<T, Func<CardViewModel, bool>> predicateFactory)
{
cards = cards.OrderBy(order);
foreach (T value in Enum.GetValues(typeof(T)))
{
if (!cards.Any(predicateFactory(value)))
continue;
builder.Append(value.ToString() + ": ");
builder.Append(cards
.Where(predicateFactory(value))
.Sum(f => f.AmountInDeck));
builder.Append(Environment.NewLine);
foreach (CardViewModel card in cards.Where(predicateFactory(value)))
{
builder.Append(card.AmountInDeck.ToString()
+ "\t"
+ card.Name.Name
+ Environment.NewLine);
}
builder.Append(Environment.NewLine);
}
}
您对AddSections
的通话如下:
this.AddSections<CardTypes>(cards, builder,
m => m.CardType,
v => m => m.CardType == v);
或者,您可以简单地快速传递谓词(或谓词工厂)的需要。既然看起来你只是处理枚举,你可以这样做:
private void AddSections<T>(
IEnumerable<CardViewModel> cards,
StringBuilder builder,
Func<CardViewModel, T> order)
{
cards = cards.OrderBy(order);
foreach (T value in Enum.GetValues(typeof(T)))
{
if (!cards.Any(c => order(c) == value))
continue;
builder.Append(value.ToString() + ": ");
builder.Append(cards
.Where(c => order(c) == value)
.Sum(f => f.AmountInDeck));
builder.Append(Environment.NewLine);
foreach (CardViewModel card in cards.Where(c => order(c) == value))
{
builder.Append(card.AmountInDeck.ToString()
+ "\t"
+ card.Name.Name
+ Environment.NewLine);
}
builder.Append(Environment.NewLine);
}
}
然后你的电话就变成了这个:
this.AddSections<CardTypes>(cards, builder, m => m.CardType);
答案 1 :(得分:0)
你可以这样做:
private void AddSections<T>(
IEnumerable<CardViewModel> cards,
StringBuilder builder,
Func<CardViewModel, T> order,
Func<CardViewModel, T, bool> prepredicate)
{
cards = cards.OrderBy(order);
foreach (T value in Enum.GetValues(typeof(T)))
{
Func<CardViewModel, bool> predicate = f => prepredicate(f,value);
...
AddSections<CardTypes>(cards, builder, order, (f,t) => f.CardType == t);
我们为函数AddSection
提供了一个可用于构建谓词的函数。在循环内部,我们可以使用lambda构建实际的谓词。