这是重载解析中的预期行为吗?

本文关键字:重载 | 更新日期: 2023-09-27 18:02:56

让我们有以下简化代码:

UPDATE:这些方法实际上返回一个泛型类型为<T>的对象。

void Main()
{
    Foo<object>(null);
}
Bar<T> Foo<T>(T value) // first
{
    Console.WriteLine("Value: {0}", value);
    // return new Bar<T> ...
}
async void Foo<T>(Task<T> task) // second
{
    Console.WriteLine("Value from task: {0}", await task);
    // return new Bar<T> ...
}

这段代码在运行时失败了:Object reference not set to an instance of an object.我意识到编译器选择了Task<T>参数的Foo的第二次重载。因此,当试图等待null时,它会失败。

也许根据c#规范这是正确的行为,但它可能会导致真正的麻烦,因为它不是程序员想要的正确的重载。如果不是规范或编译器中的错误,在类似的情况下,编译器不应该显示一些警告吗?告诉编译器选择第一个重载的最方便的方法是什么?

这是重载解析中的预期行为吗?

在重载解析中,如果通过了null,则选择具有"most"派生类型的方法。在您的示例中,Task继承自Object,因此调用async void Foo<T>(Task<T> task)

如果你调用Foo<string>(null);,那么编译器给出一个错误,因为Task不继承string(也不继承stringTask)

重载是根据编译时类型选择的,而不是运行时类型,所以像这样的东西应该可以工作:

void Main()
{
    object value = null;
    Foo<object>(value);
}

正如在已删除的回答中提到的,您也可以先将其强制转换为对象:

Foo<object>((object)null);

Foo<object>(null as object);