如何删除c#中的模糊方法调用

时间:2017-06-21 10:26:44

标签: c# overloading

这里我有一个简单的场景,有两种方法,我从彼此得到一个模糊的调用:

这是我的代码:

public IEnumerable<JobsViewModel> GetJobsViewModels(Guid vesselId, int status, Func<JobsNoSubsYpdcResult, bool> predicate = null)
    => predicate == null
        ? Mapper.Map<IEnumerable<JobsViewModel>>(_procedureService.Tech_GetJobsNoSubsYPDC(vesselId, status))
        : Mapper.Map<IEnumerable<JobsViewModel>>(_procedureService.Tech_GetJobsNoSubsYPDC(vesselId, status).Where(predicate));

public IEnumerable<JobsViewModel> GetJobsViewModels(Guid vesselId, int status, Func<JobsViewModel, bool> predicate = null)
    => predicate == null
        ? GetJobsViewModels(vesselId, status)
        : GetJobsViewModels(vesselId, status).Where(predicate);

我不喜欢更改方法的名称,但是从第二个方法我得到错误消息:

  

不明确的调用

我想从第二个调用第一个,就像我想要做的那样,是否有人知道如何在不更改方法名称的情况下执行此操作,否则我应该更改它们?

4 个答案:

答案 0 :(得分:4)

处理此问题的最佳方法是不要有两个含糊不清的重载,这样您就不需要记住如何在您调用它们的任何地方进行特殊处理。

由于您的第二个重载调用第一个,我会说最合理的操作原因是删除该委托的默认参数值:

public IEnumerable<JobsViewModel> GetJobsViewModels(Guid vesselId, int status, Func<JobsViewModel, bool> predicate)
    => predicate == null
        ? GetJobsViewModels(vesselId, status)
        : GetJobsViewModels(vesselId, status).Where(predicate);

您还应该推断调用此方法指定委托参数的能力,但明确指定null。如果这无论如何都不可能(即三元表达式的第一部分实际上不会被使用)那么我会简化整个方法:

public IEnumerable<JobsViewModel> GetJobsViewModels(Guid vesselId, int status, Func<JobsViewModel, bool> predicate)
    => GetJobsViewModels(vesselId, status).Where(predicate);

现在,尽管如此,我还是没有真正看到第二种方法的重点,就像在外面我无论如何都可以简单地抓住.Where(...)过滤器。由于该方法不会对此谓词做任何巧妙的事情,比如传递它并在较低级别上执行它,或者优化它获取数据的方式,那么这实际上只是语法糖。

然而,这只是我的意见,而且我承认并不知道如何使用这一切。我的真正答案是第一部分,但你真的应该避免声明含糊不清的方法。

另请参阅此问题:Breaking change in method overload resolution in C# 6 - explanation?

当Roslyn进入场景时,重载分辨率发生了变化,他们决定记录更改并将其更改,而不是重新引入旧的&#34;错误&#34;。

答案 1 :(得分:2)

您需要提供可选参数并使其类型对编译器清晰,即使值为null

GetJobsViewModels(vesselId, status, (Func<JobsNoSubsYpdcResult, bool>)null)

编辑:在OP提出的特定情况下,Lasse's solution更可取。

另一方面,这个答案中显示的解决方案通常可以应用,当消除过载时,其他重载没有可选的非可选参数(例如,在调用某些{时) {3}}构造函数)。

答案 2 :(得分:2)

执行此操作的唯一方法是使用适当类型的值填充可选参数,以便编译器知道要选择哪个重载。例如:

public IEnumerable<JobsViewModel> GetJobsViewModels(
    Guid vesselId,
    int status,
    Func<JobsViewModel, bool> predicate = null)
{
    // We're never filtering by JobsNoSubsYpdcResult, but this
    // satisfies overload resolution
    Func<JobsNoSubsYpdcResult, bool> resultPredicate = null;
    return predicate == null
        ? GetJobsViewModels(vesselId, status, resultPredicate)
        : GetJobsViewModels(vesselId, status, resultPredicate).Where(predicate);
}

或者为了避免重复:

public IEnumerable<JobsViewModel> GetJobsViewModels(
    Guid vesselId,
    int status,
    Func<JobsViewModel, bool> predicate = null)
{
    // We're never filtering by JobsNoSubsYpdcResult, but this
    // satisfies overload resolution
    Func<JobsNoSubsYpdcResult, bool> resultPredicate = null;
    var allResults = GetJobsViewModels(vesselId, status, resultPredicate);
    return predicate == null
        ? allResults : allResults.Where(predicate);
}

或者为了避免重复更多重复,请引入您自己的扩展方法:

public static IEnumerable<T> OptionalWhere<T>(
    this IEnumerable<T> source,
    Func<T, bool> predicate) =>
    predicate == null ? source : source.Where(predicate);

然后你可以重写两种方法来使用它:

public IEnumerable<JobsViewModel> GetJobsViewModels(Guid vesselId, int status, Func<JobsNoSubsYpdcResult, bool> predicate = null) =>
    Mapper.Map<IEnumerable<JobsViewModel>>(_procedureService.Tech_GetJobsNoSubsYPDC(vesselId, status))
        .OptionalWhere(predicate);

public IEnumerable<JobsViewModel> GetJobsViewModels(
    Guid vesselId,
    int status,
    Func<JobsViewModel, bool> predicate = null)
{
    // We're never filtering by JobsNoSubsYpdcResult, but this
    // satisfies overload resolution
    Func<JobsNoSubsYpdcResult, bool> resultPredicate = null;
    return GetJobsViewModels(vesselId, status, resultPredicate)
        .OptionalWhere(predicate);
}

(如果您乐意将null转换为Func<JobsNoSubsYpdcResult, bool>或使用静态字段,则可以使用表达式身体方法。)

答案 3 :(得分:1)

如果你真的想要你想说的话,你需要传递正确的谓词参数,例如: GetJobsViewModels(vesselId, status, new Func<JobsNoSubsYpdcResult, bool>( x => true ));