C# 为什么可以';在这种重载解析情况下,编译器不能告诉更好的转换目标吗?(协方差)
理解关于重载解析的C#语言规范显然很难,现在我想知道为什么这个简单的例子失败了:C# 为什么可以';在这种重载解析情况下,编译器不能告诉更好的转换目标吗?(协方差),c#,delegates,covariance,overloading,overload-resolution,C#,Delegates,Covariance,Overloading,Overload Resolution,理解关于重载解析的C#语言规范显然很难,现在我想知道为什么这个简单的例子失败了: void Method(Func<string> f) { } void Method(Func<object> f) { } void Call() { Method(() => { throw new NotSupportedException(); }); } 嗯,你说得对。这里出现问题的原因是您作为参数传递的委托。它没有显式的返回类型,您只是抛出了一个异常异常基本上是
void Method(Func<string> f)
{
}
void Method(Func<object> f)
{
}
void Call()
{
Method(() => { throw new NotSupportedException(); });
}
嗯,你说得对。这里出现问题的原因是您作为参数传递的委托。它没有显式的返回类型,您只是抛出了一个异常<代码>异常基本上是一个
对象
,但它不被视为方法的返回类型。因为在异常抛出之后没有返回调用,所以编译器不确定应该使用什么重载
试试这个
void Call()
{
Method(() =>
{
throw new NotSupportedException();
return "";
});
}
现在选择重载没有问题,因为传递给返回调用的对象的类型是显式声明的。由于异常抛出而无法访问返回调用并不重要,但现在编译器知道应该使用什么重载
编辑:
至于传递null的情况,我不知道答案
我的问题很简单:我在这里遗漏了C#规范的哪一部分
总结:
- 您在实现中发现了一个已知的小错误李>
- 出于向后兼容的原因,将保留该错误
- C#3规范包含一个关于如何处理“null”案例的错误;它是在C#4规范中固定的
- 您可以在无法推断返回类型的任何lambda中复制错误行为。例如:
Method(()=>null)代码>
- 如果表达式具有类型,则选择从该类型到候选参数类型的更好转换
- 如果表达式没有类型且不是lambda,请选择转换为更好的类型
Func
优于Func
,Expression
也不能转换为Expression
!如果betterness算法对于lambda是指向表达式树还是委托是不可知的,那就好了,但在某些方面不是。这些案件变得复杂起来,我不想在这里赘述
这个小错误是一个关于实现规范实际所说内容而不是您认为它所说内容的重要性的对象课程。如果我在C#3中更加小心地确保代码与规范匹配,那么代码在“null”情况下就会失败,并且在早些时候就会清楚C#3规范是错误的。实现在类型检查之前进行lambda检查,这是一个定时炸弹,当C#4启动时,它会突然变成错误代码。无论如何,类型检查应该先完成 PS!这很好:
void Test(Func f1,Func f2,bool b){var x=b?f1:f2;}
我不能确定它,但它可能与这篇文章有关:在这里,Eric解释说函数永远不会到达它们的端点,或者任何返回实际上都没有任何返回值。因此,如果lambda是Func类型,我假设编译器会选择第一个方法而不是第二个方法。但它属于“未知类型”。以某种方式呃……)@Imi lambda本身没有委托(或表达式树)类型。对于我的lambda,也找不到返回类型。但是我的lambda肯定可以隐式转换为Func
。我的lambda也可以隐式转换为Func
。因此,这两种重载都是“适用的”。现在,一个比另一个好吗?是的,因为Func
是比Func
更好的转换目标。另请参见我对问题的补充(文本null
本身没有类型,但是null
可以隐式转换为Func
和Func
)。它正确选择null
的事实表明7.5.3.5更好的转换目标得到了正确遵守。也许在7.5.3.3中有一个问题,从表达式或之前更好地转换。我本打算在阅读说明书的过程中发布一个答案,但我想我可以说,我认为你是对的
void Call()
{
Method(() =>
{
throw new NotSupportedException();
return "";
});
}