326
Глава.12 .Обобщения
В этом определении класса для параметра-типа
T
установлено основное огра-
ничение
Stream
(из пространства имен
System.IO
), сообщающее компилятору, что
код,
использующий
PrimaryConstraintOfStream
, должен задавать аргумент типа
Stream
или производного от него типа (например,
FileStream
). Если параметр-тип
не задает основное ограничение, автоматически задается тип
System.Object
.
Однако
если в исходном тексте явно указать
System.Object
, компилятор C# выдаст ошибку
(ошибка CS0702: в ограничении не может использоваться специальный класс
object
):
error CS0702: Constraint cannot be special class 'object'
Есть два особых основных ограничения:
class
и
struct
. Ограничение
class
гарантирует компилятору, что указанный аргумент-тип
будет иметь ссылочный
тип. Этому ограничению удовлетворяют все типы-классы, типы-интерфейсы, типы-
делегаты и типы-массивы, как в следующем обобщенном классе:
internal sealed class PrimaryConstraintOfClass
where T : class {
public void M() {
T temp = null;// Допустимо, потому что тип T должен быть ссылочным
}
}
В этом примере присваивание
temp
значения
null
допустимо, потому что из-
вестно, что
T
имеет ссылочный тип, а любая переменная ссылочного типа может
быть равна
null
. При отсутствии у
T
ограничений этот код бы не скомпилировал-
ся, потому что тип
Т
мог бы быть значимым, а переменные значимого типа нельзя
приравнять к
null
.
Ограничение
struct
гарантирует компилятору, что указанный аргумент типа
будет иметь значимый тип. Этому ограничению удовлетворяют все значимые
типы, а также перечисления. Однако компилятор и CLR рассматривают любой
значимый тип
System.Nullable
как особый, и значимые типы с поддержкой
null
не подходят под это ограничение. Это объясняется тем, что для параметра
типа
Nullable
действует ограничение
struct
, а среда CLR запрещает такие
рекурсивные типы, как
Nullable>
. Значимые типы с поддержкой
null
обсуждаются в главе 19.
Пример класса, в котором параметр-тип ограничивается ключевым словом
struct
:
internal sealed class PrimaryConstraintOfStruct where T : struct {
public static T Factory() {
// Допускается, потому что у каждого значимого типа неявно
// есть открытый конструктор без параметров
return new T();
}
}
В этом примере применение к
T
оператора
new
правомерно, потому что известно,
что
T
имеет значимый тип, а у всех значимых типов неявно есть открытый конструк-
тор без параметров. Если бы тип
T
был неограниченным, ограниченным ссылочным
327
Верификация.и.ограничения
типом
или ограниченным классом, этот код не скомпилировался бы, потому что
у некоторых ссылочных типов нет открытых конструкторов без параметров.
Do'stlaringiz bilan baham: