Категории
Самые читаемые
onlinekniga.com » Компьютеры и Интернет » Программирование » Полное руководство. С# 4.0 - Шилдт Герберт

Полное руководство. С# 4.0 - Шилдт Герберт

Читать онлайн Полное руководство. С# 4.0 - Шилдт Герберт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 127 128 129 130 131 132 133 134 135 ... 188
Перейти на страницу:

Этот код выдает следующий результат.2 4 6 8 1013.4 15.4 17.4 19.4 21.40,0,0 2,2,2 4,4,4 6,6,6 8,8,8

В данном примере кода имеется ряд любопытных моментов. Прежде всего обратите внимание на объявление интерфейса ISeries в следующей строке кода.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,но не объявления ByTwos и ByTwos.Сравнение экземпляров параметра типа

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

Интерфейс IEquatable объявляется следующим образом.public interface IEquatable<T>

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

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

В ходе реализации интерфейса IEquatable обычно требуется также переопределять методы 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(), который определяет равенство одногообъекта другому.

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

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

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

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

1 ... 127 128 129 130 131 132 133 134 135 ... 188
Перейти на страницу:
На этой странице вы можете бесплатно читать книгу Полное руководство. С# 4.0 - Шилдт Герберт.
Комментарии