Страница 294 из 502
<b>Объект MyClass(0) НЕ находится в границах массива nums.</b>
<b>Объект MyClass(5) НЕ находится в границах массива nums.</b>
-----------------------------------
ПРИМЕЧАНИЕ
Если параметр типа обозначает ссылку или ограничение на базовый класс, то к экземплярам объектов, определяемых таким параметром типа, можно применять операторы == и ! =, хотя они проверяют на равенство только ссылки. А для сравнения значений придется реализовать интерфейс IComparable или же обобщенные интерфейсы IComparable<T> и IEquatable<T>.
-----------------------------------
Иерархии обобщенных классов
Обобщенные классы могут входить в иерархию классов аналогично необобщенным классам. Следовательно, обобщенный класс может действовать как базовый или производный класс. Главное отличие между иерархиями обобщенных и необобщенных классов заключается в том, что в первом случае аргументы типа, необходимые обобщенному базовому классу, должны передаваться всеми производными классами вверх по иерархии аналогично передаче аргументов конструктора.
Ниже приведен простой пример иерархии, в которой используется обобщенный базовый класс.
<b>// Простая иерархия обобщенных классов,</b>
<b>using System;</b>
<b>// Обобщенный базовый класс,</b>
<b>class Gen<T> {</b>
<b> T ob;</b>
<b> public Gen(T о) {</b>
<b> ob = о;</b>
<b> }</b>
<b> // Возвратить значение переменной ob.</b>
<b> public T GetOb() {</b>
<b> return ob;</b>
<b> }</b>
<b>}</b>
<b>// Класс, производный от класса Gen.</b>
<b>class Gen2<T> : Gen<T> {</b>
<b> public Gen2(T o) : base(o) {</b>
<b> // ...</b>
<b> }</b>
<b>}</b>
<b>class GenHierDemo {</b>
<b> static void Main() {</b>
<b> Gen2<string> g2 = new Gen2<string>("Привет");</b>
<b> Console.WriteLine(g2.GetOb());</b>
<b> }</b>
<b>}</b>
В этой иерархии класс Gen2 наследует от обобщенного класса Gen. Обратите внимание на объявление класса Gen2 в следующей строке кода.
<b>class Gen2<T> : Gen<T> {</b>
Параметр типа Т указывается в объявлении класса Gen2 и в то же время передается классу Gen. Это означает, что любой тип, передаваемый классу Gen2, будет передаваться также классу Gen. Например, в следующем объявлении:
<b>Gen2<string> g2 = new Gen2<string>("Привет");</b>
параметр типа string передается классу Gen. Поэтому переменная ob в той части класса Gen2, которая относится к классу Gen, будет иметь тип string.
Обратите также внимание на то, что в классе Gen2 параметр типа Т не используется, а только передается вверх по иерархии базовому классу Gen. Это означает, что в производном классе следует непременно указывать параметры типа, требующиеся его обобщенному базовому классу, даже если этот производный класс не обязательно должен быть обобщенным.
Разумеется, в производный класс можно свободно добавлять его собственные параметры типа, если в этом есть потребность. В качестве примера ниже приведен вариант предыдущей иерархии классов, где в класс Gen2 добавлен собственный параметр типа.
<b>// Пример добавления собственных параметров типа в производный класс,</b>
<b>using System;</b>
<b>// Обобщенный базовый класс,</b>
<b>class Gen<T> {</b>
<b> T ob; // объявить переменную типа Т</b>
<b> // Передать конструктору ссылку типа Т.</b>
<b> public Gen(T о) {</b>
<b> ob = о;</b>
<b> }</b>
<b> // Возвратить значение переменной ob.</b>
<b> public T GetOb() {</b>
<b> return ob;</b>
<b> }</b>
<b>}</b>
<b>// Класс, производный от класса Gen. В этом классе</b>
<b>// определяется второй параметр типа V.</b>
<b>class Gen2<T, V> : Gen<T> {</b>