C# 如何消除c语言中不明确的方法调用#

C# 如何消除c语言中不明确的方法调用#,c#,overloading,C#,Overloading,这里我有一个简单的场景,其中有两个方法,我从另一个方法得到一个不明确的调用: 这是我的代码: public IEnumerable<JobsViewModel> GetJobsViewModels(Guid vesselId, int status, Func<JobsNoSubsYpdcResult, bool> predicate = null) => predicate == null ? Mapper.Map<IEnumerab

这里我有一个简单的场景,其中有两个方法,我从另一个方法得到一个不明确的调用:

这是我的代码:

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);
公共IEnumerable GetJobsViewModels(Guid vesselId,int状态,Func谓词=null) =>谓词==null ? Mapper.Map(_procedureService.Tech_GetJobsNoSubsYPDC(vesselId,status)) :Mapper.Map(_procedureService.Tech_GetJobsNoSubsYPDC(vesselId,status).Where(谓词)); public IEnumerable GetJobsViewModels(Guid vesselId,int状态,Func谓词=null) =>谓词==null ? GetJobsViewModels(容器ID、状态) :GetJobsViewModels(vesselId,status).Where(谓词); 我不喜欢更改方法的名称,但从第二个方法中,我得到了错误消息:

模棱两可的调用


我想从第二个参数调用第一个参数,就像我正在尝试做的那样,有人知道我如何做到这一点而不更改方法名称,否则我应该更改它们吗?

您需要提供可选参数,并向编译器说明其类型,即使值为
null

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

编辑:在OP提出的特定情况下,最好是


另一方面,此答案中所示的解决方案可以普遍应用,也可以在消除重载歧义时应用,其中另一个重载没有可设置为非可选的可选参数(例如,在调用某些构造函数时).

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

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 GetJobsViewModels(
Guid vesselId,
国际地位,
Func谓词=null)
{
//我们从不按JobsNoSubsYpdcResult筛选,但是
//满足过载分辨率
Func resultPredicate=null;
返回谓词==null
?获取作业视图模型(容器ID、状态、结果预测)
:GetJobsViewModels(vesselId、状态、结果预测)。其中(谓词);
}
或者为了避免重复:

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 IEnumerable GetJobsViewModels(
Guid vesselId,
国际地位,
Func谓词=null)
{
//我们从不按JobsNoSubsYpdcResult筛选,但是
//满足过载分辨率
Func resultPredicate=null;
var allResults=GetJobsViewModels(vesselId、status、resultPredicate);
返回谓词==null
?allResults:allResults.Where(谓词);
}
或者,为了避免更多重复,请介绍您自己的扩展方法:

public static IEnumerable<T> OptionalWhere<T>(
    this IEnumerable<T> source,
    Func<T, bool> predicate) =>
    predicate == null ? source : source.Where(predicate);
公共静态IEnumerable选项where(
这是一个数不清的来源,
Func谓词)=>
谓词==null?source:source.Where(谓词);
然后您可以重写这两种方法以使用:

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);
}
public IEnumerable GetJobsViewModels(Guid vesselId,int status,Func predicate=null)=>
Mapper.Map(_procedureService.Tech_GetJobsNoSubsYPDC(vesselId,status))
.可选where(谓词);
公共IEnumerable GetJobsViewModels(
Guid vesselId,
国际地位,
Func谓词=null)
{
//我们从不按JobsNoSubsYpdcResult筛选,但是
//满足过载分辨率
Func resultPredicate=null;
返回GetJobsViewModels(vesselId、状态、结果预测)
.可选where(谓词);
}

(如果您愿意将
null
强制转换为
Func
或使用静态字段,则可以使用表达式体方法。)

如果您确实想要所需的内容,则需要传递适当的谓词参数,例如
GetJobsViewModels(vesselId、status、new Func(x=>true))

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

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

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


现在,说了这么多,我真的看不出第二种方法的意义,因为在外部,我可以简单地插入一个
。Where(…)
过滤器。由于该方法不能巧妙地处理这个谓词,比如传递它并在较低的级别上执行,或者优化它获取数据的方式,因此这实际上只是语法上的糖分

然而,这只是我的观点,我承认我不知道这一切将如何使用。我真正的答案是第一部分,你真的应该避免声明模棱两可的方法


另请参见以下问题:


当Roslyn进入现场时,过载分辨率发生了变化,他们决定记录这一变化,并使其中断,而不是重新引入旧的“错误”。

请显示给你的那个错误的电话。@LasseV.Karlsen:我想它已经存在了。第二个表达式的主体包含对所描述方法的调用。如果跳过可选参数,那么这两个方法是完全相同的,编译器应该如何知道?或者,您可以简单地删除重载的默认值,如果您对它进行ommit,则不希望它调用,很可能是第二个重载。换句话说,只有在您实际指定委托的情况下,才可以调用第二个重载。如果没有谓词,第二个重载只会转发到第一个重载-因此实际上没有必要在没有谓词的情况下调用第二个重载,因此它不需要默认值。“无论如何,我不太明白第二个方法的意义,因为在外部,我可以简单地使用
。其中(…)
”-嗯,如果OP需要提供一个带有特定签名的方法来接受谓词(因为外部代码会通过委托像那样调用它),那么它可能有它的用途。我本来想这样做,但真正的问题在于两个模型的属性<代码>作业视图模型
public IEnumerable<JobsViewModel> GetJobsViewModels(Guid vesselId, int status, Func<JobsViewModel, bool> predicate)
    => GetJobsViewModels(vesselId, status).Where(predicate);