Вход/Регистрация
Полное руководство. С# 4.0
вернуться

Шилдт Герберт

Шрифт:

Ниже приведен результат выполнения этой программы. Метод GetOb из класса Gen возвращает результат: 88 Метод GetOb из класса Gen2 возвращает результат: 99

Как следует из результата выполнения приведенной выше программы, переопреде ляемый вариант метода GetOb вызывается для объекта типа Gen2, а его вариант из базового класса вызывается для объекта типа Gen.

Обратите внимание на следующую строку кода. iOb = new Gen2<int>(99);

Такое присваивание вполне допустимо, поскольку iOb является переменной типа Gen. Следовательно, она может ссылаться на любой объект типа Gen или же объект класса, производного от Gen, включая и Gen2. Разумеется, пере менную iOb нельзя использовать, например, для ссылки на объект типа Gen2, поскольку это может привести к несоответствию типов. Перегрузка методов с несколькими параметрами типа

Методы, параметры которых объявляются с помощью параметров типа, могут быть перегружены. Но правила их перегрузки упрощаются по сравнению с методами без параметров типа. Как правило, метод, в котором параметр типа служит для указания типа данных параметра этого метода, может быть перегружен при условии, что сиг натуры обоих его вариантов отличаются. Это означает, что оба варианта перегружае мого метода должны отличаться по типу или количеству их параметров. Но типовые различия должны определяться не по параметру обобщенного типа, а исходя из ар гумента типа, подставляемого вместо параметра типа при конструировании объекта этого типа. Следовательно, метод с параметрами типа может быть перегружен таким образом, что он окажется пригодным не для всех возможных случаев, хотя и будет вы глядеть верно.

В качестве примера рассмотрим следующий обобщенный класс. // Пример неоднозначности, к которой может привести // перегрузка методов с параметрами типа. // // Этот код не подлежит компиляции. using System; // Обобщенный класс, содержащий метод Set, перегрузка // которого может привести к неоднозначности. class Gen<T, V> { Т оb1; V ob2; // ... // В некоторых случаях эти два метода не будут // отличаться своими параметрами типа. public void Set(T о) { ob1 = о; } public void Set(V о) { ob2 = о; } } class AmbiguityDemo { static void Main { Gen<int, double> ok = new Gen<int, double>; Gen<int, int> notOK = new Gen<int, int>; ok.Set(10); // верно, поскольку аргументы типа отличаются notOK.Set(10); // неоднозначно, поскольку аргументы ничем не отличаются! } }

Рассмотрим приведенный выше код более подробно. Прежде всего обратите вни мание на то, что класс Gen объявляется с двумя параметрами типа: Т и V. В классе Gen метод Set перегружается по параметрам типа Т и V, как показано ниже. public void Set(T о) { ob1 = о; } public void Set(V о) { ob2 = о; }

Такой подход кажется вполне обоснованным, поскольку типы Т и V ничем внешне не отличаются. Но подобная перегрузка таит в себе потенциальную неоднозначность. При таком объявлении класса Gen не соблюдается никаких требований к разли чению типов Т и V. Например, нет ничего принципиально неправильного в том, что объект класса Gen будет сконструирован так, как показано ниже. Ger<int, int> notOK = new Gen<int, int>;

В данном случае оба типа, Т и V, заменяются типом int. В итоге оба варианта мето да Set оказываются совершенно одинаковыми, что, разумеется, приводит к ошибке. Следовательно, при последующей попытке вызвать метод Set для объекта notOK в методе Main появится сообщение об ошибке вследствие неоднозначности во время компиляции.

Как правило, методы с параметрами типа перегружаются при условии, что объект конструируемого типа не приводит к конфликту. Следует, однако, иметь в виду, что ограничения на типы не учитываются при разрешении конфликтов, возникающих при перегрузке методов. Поэтому ограничения на типы нельзя использовать для исключе ния неоднозначности. Конструкторы, операторы и индексаторы с параметрами типа могут быть перегружены аналогично конструкторам по тем же самым правилам. Ковариантность и контравариантность в параметрах обобщенного типа

В главе 15 ковариантность и контравариантность были рассмотрены в связи с не обобщенными делегатами. Эта форма ковариантности и контравариантности по- прежнему поддерживается в С#, поскольку она очень полезна. Но в версии C# 4.0 воз можности ковариантности и контравариантности были расширены до параметров обобщенного типа, применяемых в обобщенных интерфейсах и делегатах. Ковариант ность и контравариантность применяется, главным образом, для рационального разре шения особых ситуаций, возникающих в связи с применением обобщенных интерфей сов и делегатов, определенных в среде .NET Framework. И поэтому некоторые интер фейсы и делегаты, определенные в библиотеке, были обновлены, чтобы использовать ковариантность и контравариантность параметров типа. Разумеется, преимуществами ковариантности и контравариантности можно также воспользоваться в интерфейсах и делегатах, создаваемых собственными силами. В этом разделе механизмы ковариант ности и контравариантности параметров типа поясняются на конкретных примерах. Применение ковариантности в обобщенном интерфейсе

Применительно к обобщенному интерфейсу ковариантность служит средством, разрешающим методу возвращать тип, производный от класса, указанного в пара метре типа. В прошлом возвращаемый тип должен был в точности соответствовать параметру типа в силу строгой проверки обобщений на соответствие типов. Кова риантность смягчает это строгое правило таким образом, чтобы обеспечить типовую безопасность. Параметр ковариантного типа объявляется с помощью ключевого слова out, которое предваряет имя этого параметра.

Для того чтобы стали понятнее последствия применения ковариантности, обратим ся к конкретному примеру. Ниже приведен очень простой интерфейс IMyCoVarGenIF, в котором применяется ковариантность. // В этом обобщенном интерфейсе поддерживается ковариантность. public interface IMyCoVarGenIF<out Т> { Т GetObject; }

Обратите особое внимание на то, как объявляется параметр обобщенного типа Т. Его имени предшествует ключевое слово out. В данном контексте ключевое слово out обозначает, что обобщенный тип Т является ковариантным. А раз он ковариантный, то метод GetObject может возвращать ссылку на обобщенный тип Т или же ссылку на любой класс, производный от типа Т.

  • Читать дальше
  • 1
  • ...
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: