[英]How do I refactor methods with different signatures but almost identical bodies?
Given this private method: 鉴于这种私人方法:
private static IEnumerable<LedgerSummary> FilterLedgers(IList<LedgerSummary> ledgers, List<ExcludedLedgerAccount> excludedLedgerAccounts)
{
var excludedLedgerEntries = ledgers.Where(x => excludedLedgerAccounts.Any(y => y.LedgerAccount == x.LedgerAccount)).ToList();
var filteredLedgers = ledgers.Except(excludedLedgerEntries).ToList();
// do some more filtering
return filteredLedgers;
}
and this one: 还有这个:
private static IEnumerable<LedgerPosting> FilterLedgers(IList<LedgerPosting> ledgers, List<ExcludedLedgerAccount> excludedLedgerAccounts)
{
var excludedLedgerEntries = ledgers.Where(x => excludedLedgerAccounts.Any(y => y.LedgerAccount == x.DistributionAccountLedgerAccount)).ToList();
var filteredLedgers = ledgers.Except(excludedLedgerEntries).ToList();
// do some more filtering
return filteredLedgers;
}
what's the best way to refactor them so that I'm not repeating what is essentially the same logic in the method bodies? 什么是重构它们的最佳方法,以便我不重复方法体中基本相同的逻辑?
The reason why it's not so straightforward ( in my mind ) is because the method signatures are slightly different in that one's taking (and returning) a ' List
' of LedgerSummary
s and the other LedgerPostings
s, and each of these have different property names (that map to the same properties in ExcludedLedgerAccount
). 它之所以不那么简单( 在我看来 )是因为方法签名与
LedgerSummary
和其他LedgerPostings
的' List
'的获取(和返回)略有不同,并且每个都具有不同的属性名称(映射到ExcludedLedgerAccount
的相同属性。
Unfortunately, I can't change the properties in either of those two classes or to use a common interface, for example, for reasons that would lengthen this discourse! 不幸的是,我无法更改这两个类中的任何一个属性或使用通用接口,例如,出于延长此话语的原因!
I know the answer's really straightforward (so I apologise in advance) but I seem to be having a programmer's block at the minute. 我知道答案非常简单(所以我提前道歉)但我似乎在一分钟就遇到了程序员 。
Try something like this (don't have a VS at hand now, might require a bit of debugging) 尝试这样的事情(现在手头没有VS,可能需要一些调试)
private static IEnumerable<T> FilterLedgers<T> FilterLedgers(
IList<T> ledgers,
List<ExcludedLedgerAccount> excludedLedgerAccounts,
Func<T, ExcludedLedgerAccount, bool> selector)
{
var excludedLedgerEntries = ledgers.Where(x => excludedLedgerAccounts.Any(y => selector(x, y)).ToList();
var filteredLedgers = ledgers.Except(excludedLedgerEntries).ToList();
// do some more filtering
return filteredLedgers;
}
And use it: 并使用它:
IEnumerable<LedgerSummary> result = FilterLedgers<LedgerSummary>(input, exclude, (i, e) => i.LedgerAccount == e.LedgerAccount);
IEnumerable<LedgerPosting> result = FilterLedgers<LedgerSummary>(input, exclude, (i, e) => i.LedgerAccount == e.DistributionAccountLedgerAccount);
You can extract a predicate that you're using in the Any extension method: 您可以在Any扩展方法中提取您正在使用的谓词:
private static IEnumerable<LedgerSummary> FilterLedgersImpl(IEnumerable<LedgerSummary> ledgers, Func<LedgerSummary, LedgerAccount, bool> predicate)
{
var excludedLedgerEntries =
ledgers
.Where(x => excludedLedgerAccounts.Any(y => predicate(x, y)))
.ToList();
var filteredLedgers = ledgers.Except(excludedLedgerEntries).ToList();
// do some more filtering
return filteredLedgers;
}
And then you can use this helper method directly: 然后你可以直接使用这个辅助方法:
var list1 = FilderLedgersImpl(ledgers, (x, y) => y.LedgerAccount == x.LedgerAccount);
var list2 = FilderLedgersImpl(ledgers, (x, y) => y.LedgerAccount == x.DistributionAccountLedgerAccount);
Unless LedgerSummary and LedgerPosting share a common base class that does all the work you need (in which case you could use generics), you can't do much with this. 除非LedgerSummary和LedgerPosting共享一个共同的基类来完成你需要的所有工作(在这种情况下你可以使用泛型),否则你不能做太多。
In C++, you could use templates (or even typedefs) for a nice solution but not in C# or java... unless you wanted to use a code generator. 在C ++中,您可以使用模板(甚至是typedef)来获得一个很好的解决方案,但不能在C#或java中使用...除非您想使用代码生成器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.