Чем разрешение перегрузки группы методов отличается от разрешения перегрузки вызова метода? - PullRequest
6 голосов
/ 14 июня 2010

Следующий код не компилируется (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 делегаты со / противоположного варианта могутбыть назначенными друг другу, и делегаты могут быть созданы из методов co / противоположного варианта, так что метод ToString(object) может использоваться как Converter<T, string>, так как всегда гарантируется, что T будет преобразован в object.

Итак, первый пример (разрешение перегрузки группы методов) должен найти единственный применимый метод string Convert.ToString(object o), такой же, как разрешение перегрузки вызова метода.Почему разрешение перегрузки группы методов и вызовов методов приводит к разным результатам?

Ответы [ 2 ]

3 голосов
/ 14 июня 2010

Это связано с тем, что дисперсия не применима к типам значений, поэтому, если вы ограничите T как where T : class, вы получите дисперсию T и первый фрагмент кода скомпилируется.

Из часто задаваемых вопросов о ковариации и контравариантности :

Дисперсия поддерживается только если тип Параметр является ссылочным типом. Дисперсия не поддерживается для значения типы.

0 голосов
/ 14 июня 2010

Второй код компилируется, потому что o выводит из object, поэтому, очевидно, вы можете вызвать метод, который принимает object в качестве ввода с любым параметром.

Однако типы делегатов не равны .Если T не равен object, сигнатуры методов не совпадают.Если, скажем, T - это int, у вас будет Converter<int, string>, который отличается от Converter<object, string.Это два полностью разных типа .

Вы сталкиваетесь с проблемами, связанными с отсутствием в C / 3.0 ко / противоречивости.Должно быть лучше в C # 4.

...