Рассмотрим приведенный выше код более подробно. Прежде всего обратите внимание на то, что классGenобъявляется с двумя параметрами типа:ТиV.В классеGenметодSet перегружается по параметрам типаТиV,как показано ниже.
public void Set (T о) { obi = о;
}
public void Set(V o) { ob2 = o;
}
Такой подход кажется вполне обоснованным, поскольку типыТиVничем внешне не отличаются. Но подобная перегрузка таит в себе потенциальную неоднозначность.
При таком объявлении классаGenне соблюдается никаких требований к различению типовТиV.Например, нет ничего принципиально неправильного в том, что объект классаGenбудет сконструирован так, как показано ниже.
Gencint, int> notOK = new Gencint, int>;
В данном случае оба типа,ТиV,заменяются типомint.В итоге оба варианта методаSet оказываются совершенно одинаковыми, что, разумеется, приводит к ошибке. Следовательно, при последующей попытке вызвать методSet для объектаnotOKв методеMain появится сообщение об ошибке вследствие неоднозначности во время компиляции.
Как правило, методы с параметрами типа перегружаются при условии, что объект конструируемого типа не приводит к конфликту. Следует, однако, иметь в виду, что ограничения на типы не учитываются при разрешении конфликтов, возникающих при перегрузке методов. Поэтому ограничения на типы нельзя использовать для исключения неоднозначности. Конструкторы, операторы и индексаторы с параметрами типа могут быть перегружены аналогично конструкторам по тем же самым правилам.
Ковариантность и контравариантность в параметрах обобщенного типа
В главе 15 ковариантность и контравариантность были рассмотрены в связи с необобщенными делегатами. Эта форма ковариантности и контравариантности по-прежнему поддерживается в С#, поскольку она очень полезна. Но в версии C# 4.0 возможности ковариантности и контравариантности были расширены до параметров обобщенного типа, применяемых в обобщенных интерфейсах и делегатах. Ковариантность и контравариантность применяется, главным образом, для рационального разрешения особых ситуаций, возникающих в связи с применением обобщенных интерфейсов и делегатов, определенных в среде .NET Framework. И поэтому некоторые интерфейсы и делегаты, определенные в библиотеке, были обновлены, чтобы использовать ковариантность и контравариантность параметров типа. Разумеется, преимуществами ковариантности и контравариантности можно также воспользоваться в интерфейсах и делегатах, создаваемых собственными силами. В этом разделе механизмы ковариантности и контравариантности параметров типа поясняются на конкретных примерах.