Jep*_*sen 16 c# delegates overloading covariance overload-resolution
理解关于重载解析的C#语言规范显然很难,现在我想知道为什么这个简单的情况失败了:
void Method(Func<string> f)
{
}
void Method(Func<object> f)
{
}
void Call()
{
Method(() => { throw new NotSupportedException(); });
}
Run Code Online (Sandbox Code Playgroud)
这给出了编译时错误CS0121,以下方法或属性之间的调用是不明确的:后跟我的两个Method函数成员(重载).
我本来期望的是,Func<string>是一个更好的转换目标比Func<object>,然后应使用第一个重载.
由于.NET 4和C#4(2010),通用委托类型Func<out TResult>已协变中TResult,并且由于该原因的隐式转换从存在Func<string>于Func<object>同时明确的隐式转换可以从存在Func<object>于Func<string>.那么它会产生Func<string>更好的转换目标,而重载分辨率应该选择第一个过载?
我的问题很简单:我在这里错过了C#规范的哪一部分?
增加:这很好用:
void Call()
{
Method(null); // OK!
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 17
我的问题很简单:我在这里错过了C#规范的哪一部分?
Method(() => null);C#5规范说更好的规则是:
如果表达式具有类型,则选择从该类型到候选参数类型的更好转换.
如果表达式没有类型且不是lambda,请选择转换为更好的类型.
如果表达式是lambda,那么首先考虑哪个参数类型更好; 如果两者都不是更好并且委托类型具有相同的参数列表,则考虑lambda的推断返回类型与委托的返回类型之间的关系.
所以预期的行为是:首先编译器应该检查一个参数类型是否明显优于另一个参数类型,无论参数是否具有类型.如果这不能解决问题并且参数是lambda,那么检查转换为参数'委托类型'返回类型的推断返回类型哪个更好.
实现中的错误是实现不这样做.相反,在参数是lambda的情况下,它完全跳过类型更好性检查并直接进入推断的返回类型更好性检查,然后由于没有推断的返回类型而失败.
我的意图是为罗斯林解决这个问题.但是,当我去实现它时,我们发现修复导致一些现实代码停止编译.(我不记得现实世界的代码是什么,我不再能够访问存在兼容性问题的数据库.)因此,我们决定维护现有的小错误.
我注意到在我在C#4中添加委托差异之前,这个bug基本上是不可能的; 在C#3中,两个不同的委托类型不可能或多或少具体,因此唯一可以应用的规则是lambda规则.由于C#3中没有可以揭示错误的测试,因此很容易编写.我的坏,对不起.
我还注意到,当你开始将表达式树类型投入混合时,分析变得更加复杂.即使Func<string>比更好Func<object>,Expression<Func<string>>也不可兑换Expression<Func<object>>!如果关于lambda是否要转移到表达式树或委托,那么更好的算法是不可知的,但它在某种程度上不是.那些案件变得复杂,我不想在这里强调这一点.
这个小错误是实现规范实际所说内容的重要性的对象课程,而不是您认为的内容.如果我在C#3中更加小心以确保代码与规范匹配,则代码在"null"情况下会失败,之后很明显C#3规范是错误的.并且实现在类型检查之前进行lambda检查,这是一个定时炸弹等待C#4转过来然后突然变成不正确的代码.无论如何都应首先进行类型检查.
| 归档时间: |
|
| 查看次数: |
636 次 |
| 最近记录: |