gpt4 book ai didi

c# - C# 6 中方法重载解析的重大变化 - 解释?

转载 作者:IT王子 更新时间:2023-10-29 04:11:20 25 4
gpt4 key购买 nike

我们公司最近从 VS2013 迁移到 VS2017。升级后,我们的代码库将不再构建。我们会得到以下错误:

The call is ambiguous between the following methods or properties: 'IRepository<T>.Get(object, params Expression<Func<T, object>>[])' and 'IRepository<T>.Get(object, params string[])'

这是调用本身:

this.mainRepository.Get(newEntity.Id);

...和接口(interface)定义:

public interface IRepository<T> where T : class
{
T Get(object id, params Expression<Func<T, object>>[] includeExprs);
T Get(object id, params string[] includeExprs);
}

我想知道这里是否有人可以解释为什么会这样。我怀疑 C# 6.0 的新改进方法重载解析功能,但查看语言规范我无法找出导致该问题的确切规则。

编辑

我写了一篇关于这个问题的后续博文:http://codewithstyle.info/method-overload-resolution-in-c-6-0-an-interesting-bug-story

最佳答案

我在升级到 Visual Studio 2015 时发现了同样的事情,所以这不是 2017 年的新功能,而是 2013 年以来的新功能。

我在 github 上报告了它:

Code that compiles in VS2013 fails with CS0121 in 2015; overloads with different params parameter types #4458 :

问题是代码不明确,新的 Roslyn 编译器在这方面比以前的编译器更严格。

作为问题 Add information about #4458 to "Overload Resolution.md" #4922 的一部分,通过更改文档而不是恢复到旧行为的操作关闭了该问题。 .

特别是,AlekseyTs对此评论:

In the interest of the future health of our overload resolution code, we decided to keep the breaking (and correct) behavior. If we get more than this single case, we may want to reevaluate.

就是这样。新的编译器对此更加严格,您需要更改代码

鉴于 AlekseyTs 的上述评论,您可能想考虑在 github 上将此报告给 Microsoft,作为一个额外的此类案例。如果这种问题在 2017 年结束后变得更加普遍,因为很多人/公司都在等待升级,正如评论所说,他们可能想要重新评估。

此外,您在(较旧的)文档中找不到任何相关内容的原因是,这是较旧编译器的“隐藏功能”,从 change they did to the documentation 中可以明显看出。 :

The old compiler implemented special rules for overload resolution (not in the language specification) in the presence of unused param-array parameters, and Roslyn's more strict interpretation of the specification (now fixed) prevented some programs from compiling.

(我的重点)


当我们在我们的代码中修复相同类型的问题时,我们最终得到这样的结果(使用您的代码的示例):

public interface IRepository<T> where T : class
{
T Get(object id, Expression<Func<T, object>>[] tieBreaker, params Expression<Func<T, object>>[] includeExprs);
T Get(object id, string tieBreaker, params string[] includeExprs);
}

注意添加了两个 tieBreaker 参数

然后我们只是将显式参数与其他参数一起包含在集合中。如果您需要能够在没有这些可选额外参数的情况下调用该方法,您应该添加第三个重载,该重载没有明确说明应该调用哪个重载,因此您的最终接口(interface)可能如下所示:

public interface IRepository<T> where T : class
{
T Get(object id);
T Get(object id, Expression<Func<T, object>>[] tieBreaker, params Expression<Func<T, object>>[] includeExprs);
T Get(object id, string tieBreaker, params string[] includeExprs);
}

关于c# - C# 6 中方法重载解析的重大变化 - 解释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42951282/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com