Страница 285 из 502
<b>class Gen<T> 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<T, V> 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<string, int> obj = new Gen<string, int>("TecT", 11);</b>
<b> //А следующая строка кода недопустима, поскольку</b>
<b> // bool не относится к ссылочному типу.</b>
<b> // Gencbool, int> obj = new Gencbool, int>(true, 11);</b>
<b> }</b>
<b>}</b>
В данном примере класс Gen принимает два аргумента с ограничениями, накладываемыми с помощью отдельных операторов where. Обратите особое внимание на объявление этого класса.
<b>class GenCT, V> where T : class</b>
<b> where V : struct {</b>
Как видите, один оператор where отделяется от другого только пробелом. Другие знаки препинания между ними не нужны и даже недопустимы.
Получение значения, присваиваемого параметру типа по умолчанию
Как упоминалось выше, при написании обобщенного кода иногда важно провести различие между типами значений и ссылочными типами. Такая потребность возникает, в частности, в том случае, если переменной параметра типа должно быть присвоено значение по умолчанию. Для ссылочных типов значением по умолчанию является null, для неструктурных типов значений — 0 или логическое значение false, если это тип bool, а для структур типа struct — объект соответствующей структуры с полями, установленными по умолчанию. В этой связи возникает вопрос: какое значение следует присваивать по умолчанию переменной параметра типа: null, 0 или нечто другое? Например, если в следующем объявлении класса Test:
<b>class Test<T> {</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<T> {</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>