|
||||||||||||||||||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Установка ограничений на параметры обобщенных классовВ настоящий момент класс CarCollection<T> привлекает нас только открытыми методами с уникальными именами. Кроме того, пользователь объекта может создать экземпляр CarCollection<T> и указать практически любой параметр типа.
Чтобы проиллюстрировать другую форму типичного непредусмотренного использования объекта, предположим, что вы создали два новых класса — SportsCar (спортивная машина) и MiniVan (минивэн), — которые являются производными от Car.
В соответствии с законами наследования, в коллекцию CarCollection<T>, созданную с параметром типа Car, можно добавлять и типы MiniVan и SportsCar.
Это синтаксически корректно, но что делать, если вдруг понадобится добавить в CarCollection<T> новый открытый метод, например, с именем PrintPetName()? Такая задача кажется простой — достаточно получить доступ к подходящему элементу из List<T> и вызвать свойство PetName.
Однако в таком виде программный код скомпилирован не будет, поскольку истинная суть <T> еще не известна, и вы не можете с уверенностью утверждать, что какой-то элемент типа List<T> будет иметь свойство PetName. Когда параметр типа не имеет никаких ограничений (как в данном случае), обобщенный тип называется свободным (unbound). По идее параметры свободного типа должны иметь только члены System.Object (которые, очевидно, не имеют свойства PetName). Вы можете попытаться “обмануть” компилятор путем преобразования элемента, возвращенного из метода индексатора List<T>, в строго типизованный объект Car, чтобы затем вызвать PetName возвращенного объекта.
Но это тоже не компилируется, поскольку компилятор не знает значения параметра типа <T> и не может гарантировать, что преобразование будет законным. Для решения именно таких проблем обобщения.NET могут опционально определяться с ограничениями, для чего используется ключевое слово where.
При наложении ограничений с помощью ключевого слова where список ограничений размещается после имени базового класса обобщенного типа и списка интерфейсов. В качестве конкретных примеров рассмотрите следующие ограничения обобщенного класса MyGenericClass.
При построении обобщенного типа, в котором указано несколько параметров типа, вы можете указать уникальный набор ограничений для каждого из таких параметров.
Если вы хотите изменить тип CarCollection<T> так, чтобы в него можно было поместить только производные от Car, вы можете записать следующее.
При таких ограничениях на CarCollection<T> реализация PrintPetName() становится очень простой, поскольку теперь компилятор может предполагать, что <T> является производным от Car. Более того, если указанный пользователем параметр типа не совместим с Car, будет сгенерирована ошибка компиляции.
Вы должны понимать, что обобщенные методы тоже могут использовать ключевое слово where. Например, если нужно гарантировать, чтобы методу Swap(), созданному в этой главе выше, передавались только типы, производные от System.ValueType, измените свой программный код так. Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.003 сек.) |