类型推断过的IEnumerable
-
11-09-2019 - |
题
有几个帖子已经关于这样的事情栈溢出,但不完全一样 - 所以道歉提前如果这是一些已经回答了
。为什么这个不行:
public class MyBase { }
public class MyUtils
{
public bool Foo<T> (T myObject) { return true; }
public bool Foo (MyBase myBaseObject) { return false; }
public void Go<T> (IEnumerable<T> items)
{
foreach (var item in items)
{
// this test fails
Assert.IsFalse (Foo (item));
}
}
}
如果我请上述围棋(),并通过在MyBase对象的负荷,每次调用富将调用通用的Foo(),它返回真。
new MyUtils ().Go (new MyBase[] { new MyBase (), new MyBase () });
为什么它不叫专业MyBase的版本呢?如果我调用foo(新MyBase())直接,它正确地推断进行的呼叫。这是因为在C#3,还是我只是被愚蠢和不正确地这样做呢?
缺乏协方差收藏谢谢!
艾萨克
解决方案
它不调用“专门”之一,因为编译器的动产当程序(在此情况下,是Go
功能)是调用该方法的编译强>,不的时,它的运行。
当编译器编译Go
功能,它具有唯一的信息是,有式T
的一些对象。它没有,你可能会在某个时间点与类型MyBase
的对象提供任何的想法。它具有唯一的选择是选择Foo<T>
过载,因此它烘烤是,在以已编译的程序。
如果你想要一个应用程序来选择在运行时过载,并通过观察,同时应用程序运行的对象选择最佳的过载,这就是所谓的“动态调度”,且仅由动态语言如Ruby使用, Python和PHP等
C#3是完全静态的,并且不支持这一点。你必须在你的代码来检查的类型,如果你想它的工作这样写if语句。 另一方面,C#4,具有一定的动态支持。如果你正在写在C#4这个代码,你可以声明如下“转到”功能:
public void Go<T> (IEnumerable<dynamic> items)
然后,将使用动态调度在运行时选择哪个过载被调用,并且将调用专业采取MyBase
过载
其他提示
据C#规范(7.4.3.2),非通用方法比普通的一个更好的,所以它应选择。
不过,我觉得一般一个在你的情况下回升,因为它是一个通用的调用上下文(以下简称“foreach”循环)。
中调用不隶属于 StackOverflow