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

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

<b>class Gen&lt;T&gt; where Т : MyClass, IMylnterface, new() {</b>

<b>// ...</b>

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

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

<b>// Использовать несколько операторов where,</b>

<b>using System;</b>

<b>// У класса Gen имеются два параметра типа, и на оба накладываются</b>

<b>// ограничения с помощью отдельных операторов where,</b>

<b>class Gen&lt;T, V&gt; where T : class</b>

<b>      where V : struct {</b>

<b>  T ob1;</b>

<b>  V ob2;</b>

<b>  public Gen(T t, V v) {</b>

<b>    ob1 = t;</b>

<b>    ob2 = v;</b>

<b>  }</b>

<b>}</b>

<b>class MultipleConstraintDemo {</b>

<b>  static void Main() {</b>

<b>    // Эта строка кода вполне допустима, поскольку</b>

<b>    // string — это ссылочный тип, a int — тип значения.</b>

<b>    Gen&lt;string, int&gt; obj = new Gen&lt;string, int&gt;(&quot;TecT&quot;, 11);</b>

<b>    //А следующая строка кода недопустима, поскольку</b>

<b>    // bool не относится к ссылочному типу.</b>

<b>    // Gencbool, int&gt; obj = new Gencbool, int&gt;(true, 11);</b>

<b>  }</b>

<b>}</b>

В данном примере класс Gen принимает два аргумента с ограничениями, накладываемыми с помощью отдельных операторов where. Обратите особое внимание на объявление этого класса.

<b>class GenCT, V&gt; where T : class</b>

<b>      where V : struct {</b>

Как видите, один оператор where отделяется от другого только пробелом. Другие знаки препинания между ними не нужны и даже недопустимы.

Получение значения, присваиваемого параметру типа по умолчанию

Как упоминалось выше, при написании обобщенного кода иногда важно провести различие между типами значений и ссылочными типами. Такая потребность возникает, в частности, в том случае, если переменной параметра типа должно быть присвоено значение по умолчанию. Для ссылочных типов значением по умолчанию является null, для неструктурных типов значений — 0 или логическое значение false, если это тип bool, а для структур типа struct — объект соответствующей структуры с полями, установленными по умолчанию. В этой связи возникает вопрос: какое значение следует присваивать по умолчанию переменной параметра типа: null, 0 или нечто другое? Например, если в следующем объявлении класса Test:

<b>class Test&lt;T&gt; {</b>

<b>Т obj;</b>

<b>// ...</b>

переменной obj требуется присвоить значение по умолчанию, то какой из двух вариантов

<b>obj = null; // подходит только для ссылочных типов или</b>

<b>obj =0; // подходит только для числовых типов и </b>

<b>// перечислений, но не для структур</b>

следует выбрать? Для разрешения этой дилеммы можно воспользоваться еще одной формой оператора default, приведенной ниже.

<b>default(тип)</b>

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

Ниже приведен короткий пример, демонстрирующий данную форму оператора

default.

<b>// Продемонстрировать форму оператора default.</b>

<b>using System;</b>

<b>class MyClass {</b>

<b>  //...</b>

<b>}</b>

<b>// Получить значение, присваиваемое параметру типа Т по умолчанию,</b>

<b>class Test&lt;T&gt; {</b>

<b>  public T obj;</b>

<b>  public Test() {</b>

<b>    // Следующий оператор годится только для ссылочных типов.</b>

<b>    // obj = null; //не годится</b>

<b>    // Следующий оператор годится только для типов значений.</b>

<b>    // obj = 0; // не годится</b>

<b>    // А этот оператор годится как для ссылочных типов,</b>

<b>    // так и для типов значений,</b>

<b>    obj = default(T); // Годится!</b>

<b>  }</b>

<b>  // ...</b>