简体   繁体   English

如何重构具有不同签名但几乎相同的主体的方法?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM