// Обобщенный класс, содержащий метод Set(), перегрузка // которого может привести к неоднозначности, class Gen<T, V> {

Т obi;

V ob2 ;

// ...

// В некоторых случаях эти два метода не будут // отличаться своими параметрами типа, public void Set(T о) { obi = о;

}

public void Set(V о) { f ob2 = o;

}

}

class AmbiguityDemo { static void Main() {

Gen<int, double> ok = new Gencint, double>();

Gen<int, int> notOK = new Gencint, int>();

ok.Set(10); // верно, поскольку аргументы типа отличаются

notOK.Set(10); // неоднозначно, поскольку аргументы ничем не отличаются!

}

}

Рассмотрим приведенный выше код более подробно. Прежде всего обратите внимание на то, что класс 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. И поэтому некоторые интерфейсы и делегаты, определенные в библиотеке, были обновлены, чтобы использовать ковариантность и контравариантность параметров типа. Разумеется, преимуществами ковариантности и контравариантности можно также воспользоваться в интерфейсах и делегатах, создаваемых собственными силами. В этом разделе механизмы ковариантности и контравариантности параметров типа поясняются на конкретных примерах.

Применение ковариантности в обобщенном интерфейсе

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату