Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Руководство_по_C#.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
10.01 Mб
Скачать

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

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

where T : class

В этой форме с оператором where ключевое слово class указывает на то, что аргумент T должен быть ссылочного типа. Следовательно, всякая попытка использовать тип значения, например int или bool, вместо T приведет к ошибке во время компиляции. Ниже приведена общая форма ограничения типа значения:

where T : struct

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

Как правило, пустое значение нельзя присвоить переменной типа значения. (Исключением из этого правила является обнуляемый тип, который представляет собой специальный тип структуры, инкапсулирующий тип значения и допускающий пустое значение (null).) Следовательно, в отсутствие ограничения такое присваивание было бы недопустимым, и код не подлежал бы компиляции. Это один из тех случаев, когда для обобщенного кода может оказаться очень важным различие между типами значений и ссылочными типами.

Ограничение типа значения является дополнением ограничения ссылочного типа. Оно просто гарантирует, что любой аргумент, обозначающий тип, должен быть типа значения, в том числе struct и enum.

Давайте рассмотрим пример:

using System;

namespace ConsoleApplication1

{

struct UI

{

public UI(string Name, int Age)

{

this.Name = Name;

this.Age = Age;

}

public string Name;

public int Age;

}

// Обобщенный класс, использующий ограничение на тип значения

class UserInfo<T> where T : struct

{

T obj;

public UserInfo(T ob) { obj = ob; }

}

class Program

{

static void Main()

{

UI user1 = new UI("Alexandr",26);

UserInfo<UI> user = new UserInfo<UI>(user1);

}

}

}

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

11.7Иерархии обобщенных классов

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

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

Ниже представлен пример создания сложной иерархии обобщенных классов:

using System;

namespace ConsoleApplication1

{

class Class1<T> { }

// Унаследованный обобщенный класс

class Class2_1<T> : Class1 { }

// Ещё один унаследованный класс с собственными параметрами

class Class2_2<T, V> : Class1 { }

class Class3<T, V, E, G> : Class2_2 { }

// Обычный необобщенный класс

class SomeClass

{ }

// Унаследованный от обычного класса обобщенный класс

class ObClass<T> : SomeClass

{ }

class Program

{

static void Main()

{ }

}

}

Пример программы содержит ошибки компиляции – надо разбираться - ОВН

Как видите обобщенный класс можно так же наследовать от необобщенного. Структура наследования обобщенных классов из вышеуказанного примера представлена ниже: