Нашли ошибку или опечатку? Выделите текст и нажмите

Поменять цветовую

гамму сайта?

Поменять
Обновления сайта
и новые разделы

Рекомендовать в Google +1

Ограниченные типы

64

Допустим, что требуется создать метод, оперирующий содержимым потока, включая объекты типа FileStream или MemoryStream. На первый взгляд, такая ситуация идеально подходит для применения обобщений, но при этом нужно каким-то образом гарантировать, что в качестве аргументов типа будут использованы только типы потоков, но не int или любой другой тип. Кроме того, необходимо как-то уведомить компилятор о том, что методы, определяемые в классе потока, будут доступны для применения. Так, в обобщенном коде должно быть каким-то образом известно, что в нем может быть вызван метод Read().

Для выхода из подобных ситуаций в C# предусмотрены ограниченные типы. Указывая параметр типа, можно наложить определенное ограничение на этот параметр. Это делается с помощью оператора where при указании параметра типа:

class имя_класса<параметр_типа> where параметр_типа : ограничения { // ...

где ограничения указываются списком через запятую.

В C# предусмотрен ряд ограничений на типы данных:

Ограничение на базовый класс

Требует наличия определенного базового класса в аргументе типа. Это ограничение накладывается указанием имени требуемого базового класса. Разновидностью этого ограничения является неприкрытое ограничение типа, при котором на базовый класс указывает параметр типа, а не конкретный тип. Благодаря этому устанавливается взаимосвязь между двумя параметрами типа.

Ограничение на интерфейс

Требует реализации одного или нескольких интерфейсов аргументом типа. Это ограничение накладывается указанием имени требуемого интерфейса.

Ограничение на конструктор

Требует предоставить конструктор без параметров в аргументе типа. Это ограничение накладывается с помощью оператора new().

Ограничение ссылочного типа

Требует указывать аргумент ссылочного типа с помощью оператора class.

Ограничение типа значения

Требует указывать аргумент типа значения с помощью оператора struct.

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

Связь между параметрами типа с помощью ограничений

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

class MyObj<T, V> where V : T { ...

В этом объявлении оператор where уведомляет компилятор о том, что аргумент типа, привязанный к параметру типа V, должен быть таким же, как и аргумент типа, привязанный к параметру типа Т, или же наследовать от него. Если подобная связь отсутствует при объявлении объекта типа MyObj, то во время компиляции возникнет ошибка. Такое ограничение на параметр типа называется неприкрытым ограничением типа.

С параметром типа может быть связано несколько ограничений. В этом случае ограничения указываются списком через запятую. В этом списке первым должно быть указано ограничение class либо struct, если оно присутствует, или же ограничение на базовый класс, если оно накладывается. Указывать ограничения class или struct одновременно с ограничением на базовый класс не разрешается. Далее по списку должно следовать ограничение на интерфейс, а последним по порядку — ограничение new().

Например, следующее объявление считается вполне допустимым:

class MyObj<T> where T : MyClass, IMyInterface, new() {
// ...

В данном случае параметр типа T должен быть заменен аргументом типа, наследующим от класса MyClass, реализующим интерфейс IMyInterface и использующим конструктор без параметра.

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

Alexandr Erohin ✯ alexerohinzzz@gmail.com © 2011 - 2017