Kniga-Online.club
» » » » Герберт Шилдт - C# 4.0: полное руководство

Герберт Шилдт - C# 4.0: полное руководство

Читать бесплатно Герберт Шилдт - C# 4.0: полное руководство. Жанр: Программирование издательство -, год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:

public interface ISeries<T> {

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

А теперь обратите внимание на следующее объявление класса ByTwos, реализующего интерфейс ISeries.

class ByTwos<T> : ISeries<T> {

Параметр типа Т указывается не только при объявлении класса ByTwos, но и при объявлении интерфейса ISeries. И это очень важно. Ведь класс, реализующий обобщенный вариант интерфейса, сам должен быть обобщенным. Так, приведенное ниже объявление недопустимо, поскольку параметр типа Т не определен.

class ByTwos : ISeries<T> { // Неверно!

Аргумент типа, требующийся для интерфейса ISeries, должен быть передан классу ByTwos. В противном случае интерфейс никак не сможет получить аргумент типа.

Далее переменные, хранящие текущее значение в последовательном ряду (val) и его начальное значение (start), объявляются как объекты обобщенного типа Т. После этого объявляется делегат IncByTwo. Этот делегат определяет форму метода, используемого для увеличения на два значения, хранящегося в объекте типа Т. Для того чтобы в классе ByTwos могли обрабатываться данные любого типа, необходимо каким-то образом определить порядок увеличения на два значения каждого типа данных. Для этого конструктору класса ByTwos передается ссылка на метод, выполняющий увеличение на два. Эта ссылка хранится в переменной экземпляра делегата incr. Когда требуется сгенерировать следующий элемент в последовательном ряду, этот метод вызывается с помощью делегата incr.

А теперь обратите внимание на класс ThreeD. В этом классе инкапсулируются координаты трехмерного пространства (X,Z,Y). Его назначение — продемонстрировать обработку данных типа класса в классе ByTwos.

Далее в классе GenIntfDemo объявляются три метода увеличения на два для объектов типа int, double и ThreeD. Все эти методы передаются конструктору класса ByTwos при создании объектов соответствующих типов. Обратите особое внимание на приведенный ниже метод ThreeDPlusTwo().

// Определить метод увеличения на два каждого

// последующего значения координат объекта типа ThreeD.

static ThreeD ThreeDPlusTwo(ThreeD v) {

  if(v==null) return new ThreeD(0, 0, 0);

  else return new ThreeD(v.x + 2, v.y + 2, v.z + 2);

}

В этом методе сначала проверяется, содержит ли переменная экземпляра v пустое значение (null). Если она содержит это значение, то метод возвращает новый объект типа ThreeD со всеми обнуленными полями координат. Ведь дело в том, что переменной v по умолчанию присваивается значение типа default(Т) в конструкторе класса ByTwos. Это значение оказывается по умолчанию нулевым для типов значений и пустым для типов ссылок на объекты. Поэтому если предварительно не был вызван метод SetStart(), то перед первым увеличением на два переменная v будет содержать пустое значение вместо ссылки на объект. Это означает, что для первого увеличения на два требуется новый объект.

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

public interface ISeries<T> where T : class {

Если реализуется именно такой вариант интерфейса ISeries, в реализующем его классе следует указать то же самое ограничение на параметр типа Т, как показано ниже.

class ByTwos<T> : ISeries<T> where T : class {

В силу ограничения ссылочного типа этот вариант интерфейса ISeries нельзя применять к типам значений. Поэтому если реализовать его в рассматриваемом здесь примере программы, то допустимым окажется только объявление ByTwos<ThreeD>, но не объявления ByTwos<int> и ByTwos<double>.

Сравнение экземпляров параметра типа

Иногда возникает потребность сравнить два экземпляра параметра типа. Допустим, что требуется написать обобщенный метод IsIn(), возвращающий логическое значение true, если в массиве содержится некоторое значение. Для этой цели сначала можно попробовать сделать следующее.

// Не годится!

public static bool IsIn<T>(T what, T[] obs) {

  foreach(T v in obs)

    if(v == what) // Ошибка! return true;

  return false;

}

К сожалению, эта попытка не пройдет. Ведь параметр Т относится к обобщенному типу, и поэтому компилятору не удастся выяснить, как сравнивать два объекта. Требуется ли для этого поразрядное сравнение или же только сравнение отдельных полей? А возможно, сравнение ссылок? Вряд ли компилятор сможет найти ответы на эти вопросы. Правда, из этого положения все же имеется выход.

Для сравнения двух объектов параметра обобщенного типа они должны реализовывать интерфейс IComparable или IComparable<T> и/или интерфейс IEquatable<T>. В обоих вариантах интерфейса IComparable для этой цели определен метод СоmрагеТо(), а в интерфейсе IEquatable<T> — метод Equals(). Разновидности интерфейса IComparable предназначены для применения в тех случаях, когда требуется определить относительный порядок следования двух объектов. А интерфейс IEquatable служит для определения равенства двух объектов. Все эти интерфейсы определены в пространстве имен System и реализованы во встроенных в C# типах данных, включая int, string и double. Но их нетрудно реализовать и для собственных создаваемых классов. Итак, начнем с обобщенного интерфейса IEquatable<T>. Интерфейс IEquatable<T> объявляется следующим образом.

public interface IEquatable<T>

Сравниваемый тип данных передается ему в качестве аргумента типа Т. В этом интерфейсе определяется метод Equals(), как показано ниже.

bool Equals(Т other)

В этом методе сравниваются вызывающий объект и другой объект, определяемый параметром other. В итоге возвращается логическое значение true, если оба объекта равны, а иначе — логическое значение false.

В ходе реализации интерфейса IEquatable<T> обычно требуется также переопределять методы GetHashCode() и Equals(Object), определенные в классе Object, чтобы они оказались совместимыми с конкретной реализацией метода Equals(). Ниже приведен пример программы, в которой демонстрируется исправленный вариант упоминавшегося ранее метода IsIn().

// Требуется обобщенный интерфейс IEquatable<T>.

public static bool IsIn<T>(T what, T[] obs) where T : IEquatable<T> {

  foreach(T v in obs)

  if(v.Equals(what)) // Применяется метод Equals().

    return true;

  return false;

}

Обратите внимание в приведенном выше примере на применение следующега ограничения.

where Т : IEquatable<T>

Это ограничение гарантирует, что только те типы, в которых реализован интерфейс IEquatable, являются действительными аргументами типа для метода IsIn(). Внутри этого метода применяется метод Equals(), который определяет равенство одного объекта другому.

Для определения относительного порядка следования двух элементов применяется интерфейс ICompагable. У этого интерфейса имеются две формы: обобщенная и необобщенная. Обобщенная форма данного интерфейса обладает преимуществом обеспечения типовой безопасности, и поэтому мы рассмотрим здесь именно ее. Обобщенный интерфейс IComparable<T> объявляется следующим образом.

public interface IComparable<T>

Сравниваемый тип данных передается ему в качестве аргумента типа Т. В этом интерфейсе определяется метод CompareTo(), как показано ниже.

int CompareTo(Т other)

В этом методе сравниваются вызывающий объект и другой объект, определяемый параметром other. В итоге возвращается нуль, если вызывающий объект оказывается больше, чем объект other; и отрицательное значение, если вызывающий объект оказывается меньше, чем объект other.

Для того чтобы воспользоваться методом CompareTo(), необходимо указать ограничение, которое требуется наложить на аргумент типа для реализации обобщенного интерфейса IComparable<T>. А затем достаточно вызвать метод CompareTo(), чтобы сравнить два экземпляра параметра типа.

Перейти на страницу:

Герберт Шилдт читать все книги автора по порядку

Герберт Шилдт - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


C# 4.0: полное руководство отзывы

Отзывы читателей о книге C# 4.0: полное руководство, автор: Герберт Шилдт. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*