Рейтинговые книги
Читем онлайн C# 4.0: полное руководство - Герберт Шилдт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 158 159 160 161 162 163 164 165 166 ... 294

Gen<A, В> х = new Gen<A, В>();

оно вполне допустимо, поскольку класс В наследует от класса А. Но второе объявление

// Gen<B, А> у = new Gen<B, А>();

недопустимо, поскольку класс А не наследует от класса В.

Применение нескольких ограничений

С параметром типа может быть связано несколько ограничений. В этом случае ограничения указываются списком через запятую. В этом списке первым должно быть указано ограничение class либо struct, если оно присутствует, или же ограничение на базовый класс, если оно накладывается. Указывать ограничения class или struct одновременно с ограничением на базовый класс не разрешается. Далее по списку должно следовать ограничение на интерфейс, а последним по порядку — ограничение new(). Например, следующее объявление считается вполне допустимым.

class Gen<T> where Т : MyClass, IMylnterface, new() {

// ...

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

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

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

using System;

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

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

class Gen<T, V> where T : class

      where V : struct {

  T ob1;

  V ob2;

  public Gen(T t, V v) {

    ob1 = t;

    ob2 = v;

  }

}

class MultipleConstraintDemo {

  static void Main() {

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

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

    Gen<string, int> obj = new Gen<string, int>("TecT", 11);

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

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

    // Gencbool, int> obj = new Gencbool, int>(true, 11);

  }

}

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

class GenCT, V> where T : class

      where V : struct {

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

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

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

class Test<T> {

Т obj;

// ...

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

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

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

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

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

default(тип)

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

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

default.

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

using System;

class MyClass {

  //...

}

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

class Test<T> {

  public T obj;

  public Test() {

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

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

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

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

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

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

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

  }

  // ...

}

class DefaultDemo {

  static void Main() {

    // Сконструировать объект класса Test, используя ссылочный тип.

    Test<MyClass> x = new Test<MyClass>();

    if (x.obj == null)

      Console.WriteLine("Переменная x.obj имеет пустое значение <null>.");

    // Сконструировать объект класса Test, используя тип значения.

    Test<int> у = new Test<int>();

    if (у.obj == 0)

      Console.WriteLine("Переменная у.obj имеет значение 0.");

  }

}

Вот к какому результату приводит выполнение этого кода.

Переменная x.obj имеет пустое значение <null>.

Переменная у.obj имеет значение 0.

Обобщенные структуры

В C# разрешается создавать обобщенные структуры. Синтаксис для них такой же, как и для обобщенных классов. В качестве примера ниже приведена программа, в которой создается обобщенная структура XY для хранения координат X, Y.

// Продемонстрировать применение обобщенной структуры,

using System;

// Эта структура является обобщенной,

struct XY<T> {

  T х;

  T y;

  public XY(T а, T b) {

    х = а;

    y = b;

  }

  public T X {

    get { return х; }

    set { х = value; }

  }

  public T Y {

    get { return y; }

    set { y = value; }

  }

}

class StructTest {

  static void Main() {

    XY<int> xy = new XY<int>(10, 20);

    XY<double> xy2 = new XY<double>(88.0, 99.0);

    Console.WriteLine(xy.X + ", " + xy.Y);

    Console.WriteLine(xy2.X + ", " + xy2.Y);

  }

}

При выполнении этой программы получается следующий результат.

10, 20

88, 99

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

struct XY<T> where Т : struct {

// ...

Создание обобщенного метода

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

1 ... 158 159 160 161 162 163 164 165 166 ... 294
На этой странице вы можете бесплатно читать книгу C# 4.0: полное руководство - Герберт Шилдт бесплатно.
Похожие на C# 4.0: полное руководство - Герберт Шилдт книги

Оставить комментарий