C#6中方法重载分辨率的重大更改-解释吗? - c#

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

该调用在以下方法或属性之间是模棱两可的:'IRepository .Get(object,params Expression <Func > [])'和'IRepository .Get(object,params string [] )'

这里是电话本身:

this.mainRepository.Get(newEntity.Id);

...以及接口定义:

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对此进行了评论:

为了使我们的重载解决方案代码更健康,我们决定保留破坏(并纠正)行为。如果我们得到的不仅仅是单个案例,我们可能需要重新评估。

所以你有它。新的编译器对此更加严格,您需要更改代码。

鉴于AlekseyTs的上述评论,您可能需要考虑在github上向Microsoft报告此情况,作为另一种此类情况。如果这种问题在2017年到期之前变得更加普遍,因为很多人/公司都在等待升级,正如评论说他们可能想重新评估。

另外,在(较旧的)文档中找不到任何相关内容的原因是,这是较旧的编译器的“隐藏功能”,如change they did to the documentation所示:

在存在未使用的参数数组参数的情况下,旧的编译器实现了用于重载解析的特殊规则(不在语言规范中),而Roslyn对规范的更严格解释(现已修复)阻止了某些程序的编译。

(我的重点)

当我们在代码中解决了相同类型的问题时,我们最终得到了以下内容(使用您的代码的示例):

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参数的添加

然后,我们仅将显式参数包含在集合中,并将其他参数包含在内。如果您需要不使用这些可选的额外参数来调用该方法,则应添加第三个重载,该重载没有明确说明应调用哪个重载,因此您的最终接口可能如下所示:

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);
}

将谓词<T>转换为Func <T,bool> - c#

我有一个包含成员Predicate的类,希望在Linq表达式中使用该类:using System.Linq; class MyClass { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression); } private IEnumerable&…

Junit4和TestNG与Maven在一个项目中 - java

要一起运行它们,几乎没有可用的选项,但是我选择为Junit和TestNG使用不同的配置文件。但是现在的问题是排除和包含测试用例。由于如果我们在Maven的主项目中添加testNG依赖项,它将跳过所有Junit,因此我决定将其放在单独的配置文件中。所以我使用pom.xml中的以下条目从默认(主要)配置文件中排除了TestNG测试:<plugin> …

Java中的<<或>>>是什么意思? - java

This question already has answers here: Closed 7 years ago. Possible Duplicate: What does >> and >>> mean in Java?我在一些Java代码中遇到了一些陌生的符号,尽管代码可以正确编译和运行,但对于括号在此代码中的作用却感…

通过Maven编译器插件不会发生有限的包含和排除 - java

我正在使用3.6.0版的maven编译器插件,在此我们只想在特定文件夹中编译一个文件,而在该位置编译所有其他文件。例如:在文件夹应用程序中有14个文件,从那我只希望编译1个文件,但它编译了所有文件,如果我要排除,则它也不起作用。 <sourceDirectory>${basedir}/../src/java</sourceDirectory…

当我所有的都是T时,如何返回Interface <T>的实例? - java

我有一个界面:public interface ILoginResult<T> { public T get(); } 我有一个LoginPage对象:public class LoginPage<T> { ... public ILoginResult<T> login(...) { ... } } 我也有一些登录页面对…