方法组重载解析与方法调用重载解析有何不同?

6
以下代码无法编译(error CS0123: No overload for 'System.Convert.ToString(object)' matches delegate 'System.Converter<T,string>'):
class A<T> {
    void Method(T obj) {
        Converter<T, string> toString = Convert.ToString;

        // this doesn't work either (on .NET 4):
        Converter<object, string> toString2 = Convert.ToString;
        Converter<T, string> toString3 = toString2;            
    }
}

然而,这确实做到了:
class A<T> {
    void Method(T obj) {
        // o is a T, and Convert.ToString(o) is using
        // string Convert.ToString(object o)

        Converter<T, string> toString = o => Convert.ToString(o);
    }
}

在c# 4中,协变/逆变委托可以互相赋值,并且可以从协变/逆变方法创建委托,因此ToString(object)方法可以用作Converter<T, string>,因为T始终可转换为object
因此,第一个示例(方法组重载分辨率)应该找到唯一适用的方法string Convert.ToString(object o),与方法调用重载分辨率相同。为什么方法组和方法调用重载分辨率会产生不同的结果呢?
2个回答

3
这与方差不适用于值类型有关,因此如果限制Twhere T: class,则可以在T上获得方差,第一个代码片段将编译通过。
来自协变和逆变 FAQ

仅当类型参数为引用类型时才支持方差。对于值类型不支持方差。


更具体地说,它对于未受限制的 T 不起作用,因为它 可能是 值类型。 - thecoop

0
第二个代码编译成功是因为 o 是从 object 派生而来,所以显然你可以使用任何类型的参数调用以 object 作为输入的方法。
委托类型,然而,并不相等。除非 Tobject,否则方法标记不匹配。比如说,Tint,你将会有一个 Converter<int, string>,它与 Converter<object, string 不同。它们是两种完全不同的类型。
你正在碰到 C# 3.0 缺乏协变/逆变性的问题。在 C# 4 中应该会更好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接