Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 181
Текст из файла (страница 181)
898 Часть (). Библиотека Сз Интерфейс 1солтрагег существует в двух формах: обобщенной и необобщенной. Несмотря на сходство применения обеих форм данного интерфейса, между ними имеются некоторые, хотя и небольшие, отличия, рассматриваемые ниже. Применение необобщенного интерфейса 1соп(рахег В необобшенном интерфейсе 1сотлрагег определяется только один метод, Сотлраге (): ъпс Саврасе(оЬбесг оЬ21, оЬ)есг оЬ22) В методе солтраге () сравниваются объекты оЬ т1 и оЬ12. Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное — если значение объекта оЬ1'1 больше, чем у объекта оЬ)'2; и отрицательное — если значение объекта оЬ11 меньше, чем у объекта оЬ12.
А для сортировки по убывающей можно обратить результат сравнения объектов. Если же тип объекта оЬ1'1 не подходит для сравнения с объектом обт2, то в методе Солтрагето () может быть сгенерировано исключение йгдолтепСЕхсергкоп. Объект типа 1Сопрагег может быть указан при конструировании объекта класса яоггебъ15С, при вызове метода йггауъъвг. яогг (1Соврагег), а также в ряде других мест в классах коллекций. Главное преимущество применения интерфейса 1Сопрагег заключается в том, что сортировке подлежат объекты тех классов, в которых интерфейс 1СопрагаЬ1е не реализуется.
Приведенный ниже пример программы является вариантом рассматривавшегося ранее необобшенного примера программы учета товарных запасов, переделанного с целью воспользоваться интерфейсом 1Сотлрагег для сортировки перечня товарных запасов. В этом варианте программы сначала создается класс Сопр1пн, в котором реализуется интерфейс 1Сотлрагег и сравниваются два объекта класса 1пнепсогу. А затем объект класса Сотлр1пн указывается в вызове метода Яогг () для сортировки перечня товарных запасов. // Использовать необобщенный вариант интерфейса 1Созрагег. овъпя Яувгезт овъпя 5увсеи.Со11есгъопв; // Создать объект типа 1созрагег длл объектов класса 1пнепсогу. с1авв Созр1пн: 1Созрагег ( // Реализовать интерфейс 1созрагег.
рпЬ11с ьпс Соираге(оъ)есс оЬ21, оЬбесс оЬ)2) ( 1пнепсогу а, Ьт а (1пнепгогу) оЬ21; Ь (1пнепгогу) оЪ221 гесигп а.паке.созрагето(Ь.паве)т ) ) с1авв 1пнепсогу ( рнЬ11с всг1пя паве; Глава 24. Коллекции, перечисли(ели и итераторы В99 т)оеЫе сояс; Ьпс оппапот риЫ1с 1пчепгогу(ягг1по и, ОочЫе с, ьпг Ы ( паве = пт сояС = ст оппапт) = Ьт ) рчЫЬс очеггаое вггапо Тозггапо() ( гегнгп 5Сг1по.рогваг("(0,-10)Стоимостьт (1,6:С) Наличие: (2!", паве, сояг, оппапп)т с1аяя 1Соврагегпево ( вгаС1с чоки Маап() ( Совр1пч совр = пеи Совр1пч()т Кггауьаяг Ьпч пеы аггаупаяг() // добавить элементы в список. 1пч.ат)т((пеы 1пнепгогу("Кусачки", 5.95, 3))) 1пн.лс(О(пеы 1пнепгогу("Отвертки", 8.29, 2))т 1пч.ат)т((пеы 1пнепСогу("Молотки", 3.50, 4)); 1пч.ас(т((пеы 1пнепгогу("дрели", 19.88,,8))т Сопяо1е.ИгтгеЬЬпе("Перечень товарных запасов Ло сортировки:"); Гогеасп(1пчепгогу 1 Ьп Ьпн) ( Сопяо1е.игггепапе(" " + 1); ! Сопяо1е.игагеьгпе () т // Отсортировать список, используя интерфейс 1Соврагег.
Ьпч.зогс (совр) т Сопяо1е.игагепапе("Перечень товарных запасов после сортировки:") гогеасЬ(1пнепСогу 1 1п Ьпч) ( Сопяо1е.ИгагеЬЬпе(" " ч 1)т ) ) Эта версия программы дает такой же результат, как и предыдущая. Применение обобщенного интерфейса 1Совра~ех<т> Интерфейс 1соврагег<т> является обобщенным вариантом интерфейса 1соврагег. В нем определяется приведенный ниже обобщенный вариант метода Совраге () .
Ьпг Совраге(Т опут, т ооу2) 900 Часть П. Библиотека С№ В этом методе сравниваются объекты ОЬ31 и ОЬ32 и возвращается нулевое значение, если значения сравниваемых объектов равны; положительное — если значение объекта ОЬ31 больше, чем у объекта ОЬ32; и отрицательное — если значение объекта ОЬ31 меньше, чем у объекта оь32. Ниже приведена обобщенная версия предыдущей программы учета товарных запасов, в которой теперь используется интерфейс 1Соврагег<Т>. Она дает такой же результат, как и необобщенная версия этой же программы. // Использовать обобщенный вариант интерфейса 1Соврагег<Т>. пяьпч Яуягев( пя1пч Яувгев.Со11есс1опв.пепегъс) // Создать объект типа 1Соврагег<Т> для объектов класса 1пчепсогу.
с1авя совр1пч<т>: 1соврагег<т> нпеге т: 1пчепсогу ( // Реализовать интерфейс 1Соврагег<Т>. рпЫТс Тпг совраге(Т оЬ31, Т оЬ)2) ( гесигп оЪ)1.паве.СоврагеТо(оЪ32.паве); ) ) с1аяя 1пчепсогу ( роЫТс всгъпч паве; бопЫе сояг; Тпс оппапбг риЬ11с 1пчепгогу(ясгтпд и, бопЬ1е с, Тпс Ь) ( паве = и) сояс = с; оппапб = Ь; ) рПЫус очегггйе ягггпд Тоэгг1пч() ( гегогп Ясгтпд.Гогваг("(0,-10]Стоимость: (1,6:С) Наличие: (2)", паве, сояг, оппапб)' с1аяя оепег1с1соврагегпево ( ясасто чОТб Мавв() ( Совр1пч<1пчепсогу> совр = пен Совр1пч<1пчепгогу>() Ьъяс<1пчепсогу> Тпч = пен 51яс<1пчепсогу>()г // Добавить элементы в список. Тпч.лбб(пен 1пчепсогу("Кусачки", 5.95, 3)); тпч.кбб(пен 1пчепсогу("Отвертки", 8.29, 2))Г Тпч.лбе(пен 1пчепсогу('молотки', 3.50, 4))) Тпч.лбб(пен 1пчепгогу("Дрели", 19.88, 8))) Сопво1е.игьсеьтпе("Перечень товарных запасов до сортировки:"); Еогеасп(1пчепгогу 1 Тп Тпч)'( Глава 24.
Коллекции, пврвчислитвли и итвраторы 901 Сопяо1е.нгггеъ1пе (" " + 1) т ) Сопяо1е.Игъгеььпе () т // Отсортировать список, используя интерфейс 1созрагег. 1пч.яогс(соир)т Сопяо1е.Игъсеъъпе("Перечень товарных запасов после сортировки:"); гогеасп(1пчепсогу 1 ъп ъпч) ( Со(пяо1е.нгъсеъъпе(" " + 1)т ) ) ) Доступ к коллекции с помощью перечислителя К элементам коллекции нередко приходится обращаться циклически, например, для отображения каждого элемента коллекции.
Для этой цели можно, с одной стороны, организовать цикл Тогеасн, как было показано в приведенных выше примерах, а с другой — воспользоваться перечислителем. Перечислитель — это объект, который реализует необобщенный интерфейс 1епшпегагог или обобщенный интерфейс 1Еппвегасог<Т>. В интерфейсе 1Епптлегасог определяется одно свойство, Спггепс, необобщенная форма которого приведена ниже.
опэесс Соггепс ( Пест ) А в интерфейсе 1Епшлегагог<т> объявляется следующая обобщенная форма свойства Сиггептх Т Соггепг ( Пест В обеих формах свойства Ссггепс получается текущий перечисляемый элемент коллекции. Но поскольку свойство Спггепс доступно только для чтения, то перечислитель может служить только для извлечения, но не видоизменения объектов в коллекции. В интерфейсе 1еппвегасог определяются два метода. Первым из них является метод мочеиехс (), объявляемый следующим образом: Ьоо1 Мочеыехс() При каждом вызове метода мочейехс() текущее положение перечислителя смещается к следующему элементу коллекции. Этот метод возвращает логическое значение ггпе, если следующий элемент коллекции доступен, и логическое значение га1яе, если достигнут конец коллекции. Перед первым вызовом метода моченехс () значение свойства спггепс оказывается неопределенным.
ГВ принципе до первого вызова метода моченехс () перечислитель обращается к несуществующему элементу, который должен находиться перед первым элементом коллекции. Именно поэтому приходится вызывать метод моченехг (), чтобы перейти к первому элементу коллекции.) Для установки перечислителя в исходное положение, соответствующее началу коллекции, вызывается приведенный ниже метод Невес () .
чогк( невес() 902 Часть 11. Библиотека Сэ После вызова метода невес () перечисление вновь начинается с самого начала коллекции. Поэтому, прежде чем получить первый элемент коллекции, следует вызвать метод Монепехс () . В интерфейсе 1епшаегасог<т> методы моненехс () и невес () действуют по тому же самому принципу. Необходимо также обратить внимание на два следующих момента. Во-первых, пере- числитель нельзя использовать для изменения содержимого перечисляемой с его помощью коллекции. Следовательно, перечислители действуют по отношению к коллекции как к доступной только для чтения.
И во-вторых, любое изменение в перечисляемой коллекции делает перечислитель недействительным. Применение обычного перечислителя Прежде чем получить доступ к коллекции с помощью перечислителя, необходимо получить его. В каждом классе коллекции для этой цели предоставляется метод ПеГЕпппегагог (), возвращающий перечислитель в начало коллекции.
Используя этот перечислитель, можно получить доступ к любому элементу коллекции по очереди. В целом для циклического обращения к содержимому коллекции с помощью перечислителя рекомендуется придерживаться приведенной ниже процедуры. (. Получить перечислителть устанавливаемый в начало коллекции, вызвав для этой коллекции метод СеСЕпппкегагог () .
2. Организовать цикл, в котором вызывается метод моненехс () . Повторять цикл до тех пор, пока метод Монекехг () возвращает логическое значение Сгне. 3. Получить в цикле каждый элемент коллекции с помощью свойства Сиггепс. Ниже приведен пример программы, в которой реализуется данная процедура. В этой программе используется класс Аггаудвяг, но общие принципы циклического обращения к элементам коллекции с помощью перечислителя остаются неизменными для коллекций любого типа, в том числе и обобщенных. // Продемонстрировать применение перечислителя.
паунд эуягеет чвгпо яувсеи. Со11есс1опщ с1авв Епчиегагогпеео ( всастс нолв Ма1п() ( Аггауьувс 11вс = пеи Аггауьувс(1)т лог(тпг 1=от 1 < 101 1ьт) 11яГ.АПП(1) т // Использовать перечислитель для доступа к списку. 1епоиегасог егг 11яг.пегепчиегагог()т нд11е(ест.Монеиекс()) Сопво1е.игтсе(екг.Спггепс + " ")т Сопво1е.игтсеввпе()т // Повторить перечисление списка.
Глава 24. Коллелции, перечислители и итера)ори 903 ест.невес()) ни11е(егг.иочеыехг()) Содяо1е.игьге(егг.сиггеог + " ")и Сопяо1е.игьгерапе() ) ) Вот к какому результату приводит выполнение этой программы: 0123456789 0123458789 Вообще говоря, для циклического обращения к элементам коллекции цикл гогеасЬ оказывается более удобным, чем перечнслитель. Тем не менее перечислитель предоставляет больше возможностей для управления, поскольку его можно при желании всегда установить в исходное положение.