2010-06-14 5 views
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, со/противопоказана вариант делегаты могут быть отнесены к друг другу, и делегаты могут быть созданы из co/contra-variant методов, поэтому метод ToString(object) может использоваться как Converter<T, string>, так как T всегда гарантированно может быть преобразован в object.

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

ответ

3

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

От Covariance and Contravariance FAQ:

Дисперсия поддерживается только тогда, когда параметр типа является ссылочным типом. Разница не поддерживается для значений .

+0

Более конкретно, это не работает для неограниченного 'T', потому что это _might be_ тип значения. – thecoop

0

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

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

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

+0

Это в .NET 4. Я обновил свой вопрос – thecoop

Смежные вопросы