开发者

How is method group overload resolution different to method call overload resolution?

开发者 https://www.devze.com 2023-01-03 04:25 出处:网络
The following code doesn\'t compile (error CS0123: No overload for \'System.Convert.ToString(object)\' matches delegate \'System.Converter<T,string>\'):

The following code doesn't compile (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;            
    }
}

however, this does:

class A<T> {
    void Me开发者_Go百科thod(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);
    }
}

In c# 4, co/contra-variant delegates can be assigned to each other, and delegates can be created from co/contra-variant methods, so the ToString(object) method can be used as a Converter<T, string>, as T is always guarenteed to be convertable to an object.

So, the first example (method group overload resolution) should be finding the only applicable method string Convert.ToString(object o), the same as the method call overload resolution. Why is the method group & method call overload resolution producing different results?


This has to do with the fact that variance is not applicable to value types, so if you restrict T like where T : class you get variance on T and the first snippet of code will compile.

From the Covariance and Contravariance FAQ:

Variance is supported only if a type parameter is a reference type. Variance is not supported for value types.


The second code compiles because o derives from object, so obviously you can invoke a method that takes an object as input with any type of parameter.

The delegate types, however, are not equal. Unless T is object the method signatures don't match. If, say, T is int you would have a Converter<int, string> which is not the same as Converter<object, string. They are two entirely different types.

You are hitting the issues around C# 3.0's lack of co/contra-variance. Should be better in C# 4.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号