为什么编译器不能在这种重载解析情况下告诉一个更好的转换目标?(协方差)理解关于重载决议的C#语言规范显然很难,现在我想知道为什么这个简单的案例失败了:voidMethod(Funcf){}voidMethod(Funcf){}voidCall(){Method(()=>{抛出新的NotSupportedException();});这给出了编译时错误CS0121,以下方法或属性之间的调用不明确:后跟我的两个方法函数成员(重载)。我期望Func是比Func更好的转换目标,然后应该使用第一个重载。从.NET4和C#4(2010)开始,泛型委托类型Func在TResult中是协变的,因此存在从Func到Func的隐式转换,而显然没有从Func到Func的隐式转换。那么它是否会使Func成为更好的转换目标,重载决策应该选择第一个重载?我的问题很简单:我在这里遗漏了C#规范的哪一部分?添加:这很好用:voidCall(){Method(null);//好的!我的问题很简单:我在这里遗漏了C#规范的哪一部分?摘要:详细信息:C#5规范说更好的规则是:所以预期的行为是:首先编译器应该检查一个参数类型明显优于另一个,不管参数是否有类型。如果这不能解决问题并且参数是lambda,则检??查哪个更好,将推断的返回类型转换为参数的“委托类型”返回类型。实现不执行此操作是实现中的错误。相反,在参数是lambda的情况下,它会完全跳过类型完整性检查并直接转到推断的返回类型完整性检查,然后失败,因为没有推断的返回类型。我的意图是为Roslyn解决这个问题。然而,当我去实施它时,我们发现修复导致一些真实世界的代码停止编译。(我不记得真正的代码是什么,而且由于兼容性问题我无法再访问数据库。)所以我们决定维护现有的错误。我注意到在我在C#4中添加委托方差之前,这个错误基本上是不可能的;在C#3中,两种不同的委托类型不可能具有或多或少的特定性,因此唯一可以应用的规则是lambda规则。由于C#3中没有可以揭示错误的测试,因此很容易编写。我的错,对不起。我还注意到,当您开始将表达式树类型混合在一起时,分析会变得更加复杂。尽管Func比Func好,但Expression>不能转换为Expression>!更好的算法对于lambda是否将移动到表达式树或委托是不可知的,但不知何故不是。这些情况变得复杂,我不想在这里强调。这个小错误是一个实物教训,说明了了解规范实际所说的重要性,而不是你认为的那样。如果我在C#3中更加小心以确保代码与规范匹配,代码将在“空”情况下失败,之后很明显C#3规范是错误的。并且该实现在类型检查之前执行lambda检查,这是一个滴答作响的定时炸弹,等待C#4为突然出错的代码转身。无论如何,您应该先输入check。嗯,你是对的。造成这里问题的是您作为参数传递的委托。它没有明确的返回类型,您只需抛出异常即可。异常基本上是一个对象,但它不被视为方法的返回类型。由于抛出异常后调用没有返回,编译器不确定它应该使用什么重载。试试voidCall(){Method(()=>{thrownewNotSupportedException();return"";});现在,由于传递给返回调用的对象的显式声明类型,选择重载没有问题。由于抛出了异常,return调用不可达并不重要,但现在编译器知道它应该使用什么重载。编辑:至于传递null的情况,坦率地说,我不知道答案。以上是C#学习教程:为什么编译器不能在这种重载决议情况下告诉更好的转换目标?(Covariance)所有分享的内容,如果对你有用,需要了解更多C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
