Добавить в цитаты Настройки чтения

Страница 294 из 502

<b>Объект MyClass(0) НЕ находится в границах массива nums.</b>

<b>Объект MyClass(5) НЕ находится в границах массива nums.</b>

-----------------------------------

ПРИМЕЧАНИЕ

Если параметр типа обозначает ссылку или ограничение на базовый класс, то к экземплярам объектов, определяемых таким параметром типа, можно применять операторы == и ! =, хотя они проверяют на равенство только ссылки. А для сравнения значений придется реализовать интерфейс IComparable или же обобщенные интерфейсы IComparable&lt;T&gt; и IEquatable&lt;T&gt;.

-----------------------------------

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

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

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

<b>// Простая иерархия обобщенных классов,</b>

<b>using System;</b>

<b>// Обобщенный базовый класс,</b>

<b>class Gen&lt;T&gt; {</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&lt;T&gt; : Gen&lt;T&gt; {</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&lt;string&gt; g2 = new Gen2&lt;string&gt;(&quot;Привет&quot;);</b>

<b>    Console.WriteLine(g2.GetOb());</b>

<b>  }</b>

<b>}</b>

В этой иерархии класс Gen2 наследует от обобщенного класса Gen. Обратите внимание на объявление класса Gen2 в следующей строке кода.

<b>class Gen2&lt;T&gt; : Gen&lt;T&gt; {</b>

Параметр типа Т указывается в объявлении класса Gen2 и в то же время передается классу Gen. Это означает, что любой тип, передаваемый классу Gen2, будет передаваться также классу Gen. Например, в следующем объявлении:

<b>Gen2&lt;string&gt; g2 = new Gen2&lt;string&gt;(&quot;Привет&quot;);</b>

параметр типа string передается классу Gen. Поэтому переменная ob в той части класса Gen2, которая относится к классу Gen, будет иметь тип string.

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

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

<b>// Пример добавления собственных параметров типа в производный класс,</b>

<b>using System;</b>

<b>// Обобщенный базовый класс,</b>

<b>class Gen&lt;T&gt; {</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&lt;T, V&gt; : Gen&lt;T&gt; {</b>