Г. Шилдт - С#4.0 Полное руководство (1160795), страница 204
Текст из файла (страница 204)
Богхеоъхвс<зхг1пч, 1пс> овегв = лен Боггес)ъхзг<вггхпч, хпх>(згг1посоврагег.одс(1па1) 998 Часть! 1. Библиатека С№ Доступ к коллекции с помощью перечислителя К элементам коллекции нередко прихадится обращаться циклически, например, для отображения каждого элемента коллекции. С этой целью можно, с одной стороны, организовать цикл ГотеасЬ, как было показано в приведенных выше примерах, а с другой — воспользоваться перечислителем. Перечислигяель — это объект, который реализует необобщенный интерфейс 1Еппветагог или обобщенный интерфейс 1Еппветатог<Т>.
В интерфейсе 1еппвегатог определяется одно свойство, Ситтепт, необобгценная форма которого приведена ниже. оЬЗест Ситтепт ( яет; ) А в интерфейсе 1Еппветатот<т> объявляется следующая обобщенная форма свойства Сит гепт. т ситгепг ( чет/ ) В обеих формах свойства Сигтепт получаезся ~екущий перечисляемый элемент коллекции. Но поскольку свойство Спгтепс доступно только для чтения, то перечислитель может служить только для извлечения, но не видоизменения объектов в коллекции. В интерфейсе 1Еппветатог определяются два метода.
Первым из них является метод Моче((ехт (), объявляемый следующим образом. Ьо>1 Иочеиехт() При каждом вызове метода Моченехт () текущее положение перечислителя смещается к следующему элементу коллекции. Этот метод возвращает логическое значение т тее, если следующий элемент коллекции доступен, и логическое значение Та1яе, если достигнут конец коллекции. Перед первым вызовом метода МочеЫехт () значение свойства Спггепт оказывается неопределенным.
(В принципе до первого вызова метода МочеЫехт ( ) перечислитель обращается к несуществующему элементу, который должен находиться перед первым элементом коллекции. Именно поэтому приходится вызывать метод Моченехт (), чтобы перейти к первому элементу коллекции.) Для установки перечислителя в исходное положение, соответствующее началу коллекции, вызывается приведенный ниже метод Везет ( ) . чат0 Ревет() После вызова метода Везет () перечисление вновь начинается с самого начала коллекции. Поэтому, прежде чем получить первый элемент коллекции, следует вызвать метод Моченехт () . В интерфейсе 1Еппветатог<Т> методы Моченехт () и Везет () действуют потому же самому принципу. Необходимо также обратить внимание на два следующих момента.
Во-первых, перечислитель нельзя использовать для изменения содержимого перечисляемой с его помощью коллекции. Следовательно, перечислители действуют по отношению к коллекции как к доступной только для чтения. И во-вторых, любое изменение в перечисляемой коллекции делает перечислитель недействительным. Глава 2б. Кояяекции, перечисяитеяи и итераторы 999 Применение обычного перечислителя Прежде чем получить доступ к коллекции с помощью перечислителя, необходимо получить его. В каждом классе коллекции для этой цели предоставляется метод СеСЕппмегагог (), возвращающий перечислитель в начало коллекции.
Используя этот перечислитель, можно получить доступ к любому элементу коллекции по очереди. В целом, для циклического обращения к содержимому коллекции с помощью перечислителя рекомендуется придерживаться приведенной ниже процедуры. 1. Получить перечислителгь устанавливаемый в начало коллекции, вызвав для этой коллекции метод ЕеСЕппмегагог () . 2.
Организовать цикл, в котором вызывается метод Мочеиехг () . Повторять цикл до тех пор, пока метод моченехс () возвращает логическое значение ггпе. 3. Получить в цикле каждый элемент коллекции с помощью свойства Спггепг. Ниже приведен пример программы, в которой реализуется данная процедура.
В этой программе используется класс )тггауе151, но общие принципы циклического обращения к элементам коллекции с помощью перечислителя остаются неизменными для коллекций любого типа, в том числе и обобщенных. /! Продемонстрировать применение перечислителя. оя1пч 5уягеьм ояьпч зуясеп. Со11есс1опят с1авя Еповегасогоеио ( ягасьс чогс( Ма1п() ( Аггауэьяс 11яс = пен Хггаупьяс(1) бог(1пг 1=0; 1 < 101 ьтт) 1гяс.Айаг((1) 1 О Использовать перечислитель для доступа к списку. 1Епокегасог ест = 11ят.ееГЕпшпегасог(); нн11е(ест.Мочеиехс()) Сопяо1е.нг1се(ест.соггепс + " "); Сон яо1е. Игьгеььпе () // Повторить перечисление списка. ест.невес()т нп11е (ест. Монеиехс () ) Сопяо1е.нггсе(ест.сиггепс + " "); Сопяо1е.игьвевьпе()т ) ) Вот к какому результату приводит выполнение этой программы.
012345б789 01234 5б789 1000 Часть П. Библиотека С() Вообще говоря, для циклического обращения к элементам коллекции цикл Тогеасп оказывается более удобным, чем перечислитель. Тем не менее перечисли- тель предоставляет больше возможностей для управления, поскольку его можно при желании всегда установить в исходное положение. Применение перечислитебп типа 1ИсИогтаеуЕгз(зп(ееа1ое Если для организации коллекции в виде словаря, например типа НавпхаЬ1е, реализуется необобщенный интерфейс 1пьссьопагу, то для циклического обращения к элементам такой коллекции следует использовать перечислитель типа 1()1ссгопагуЕпцшегасог вместо перечислителя типа 1Епцшегахог.
Интерфейс 1Р1сг1опахунпцтехагог наследует от интерфейса 1Епцшегасох и имеет три дополнительных свойства. Первым из них является следующее свойство. ЬвсхгопагуЕпсгу Епсху ( чево ] Свойство Епсгу позволяет получить пару "ключ-значение" изперечислителя в форме структуры 01схгопагуЕпхгу. Напомним, что в структуре Р1СЬ1одагуЕпхху определяются два свойства, Кеу и уа1це, с помощью которых можно получать доступ к ключу или значению, связанному с элементом коллекции. Ниже приведены два других свойства, определяемых в интерфейсе 1()1схьопахуЕпцшегасог. оЬзесг КеУ ( чех; ) оьзесс уа1це ( дехг С помощью этих свойств осуществляется непосредственный доступ к ключу или значению. Перечислитель типа 1Р1СЬ1опагуЕпцшегагог используется аналогично обычному перечислителю, за исключением того, что текущее значение в данном случае получается с помощью свойств епьгу, кеу или 1са1це, а не свойства сцххепс.
Следовательно, приобретя перечислитель типа 1П1сс1опахуепцтегагог, необходимо вызвать метод Моченехх ( ), чтобы получить первый элемент коллекции. А для получения остальных ее элементов следует продолжить вызовы метода Моченехг ( ) . Этот метод возвращает логическое значение Та1ве, когда в коллекции больше нет ни одного элемента. В приведенном ниже примере программы элементы коллекции типа НавпхаЬ1е перечисляются с помощью перечислителя типа 101сс1опахуЕпцшехасох.
Продемонстрировать применение перечислителв типа 101сх1опагуЕпцшегагог. цвьпч зувхеьм цвгпч зувгеш.со11ессгопвг с1авв 1ввсЕпцшпешо ( вхаггс то1с( Магд() ( // Создать хеш-таблицу. НавпхаЬ1е ЬГ = пен Навпсапге(); с'/ Добавить элементы в таблицу. Ьг.яс(б("Кен", "555-7756")г Ьг.вс(С("Мэри", "555-9876"); Ьг.яс(б("Том", "555 †34"); Ьг.лоб("Тодд", "555-3452")г Глава 25. Комекции, оеречислители и итераторы 1001 Продемонстрировать применение перечислителя. 1О1сгьопагуепщпегагог егг = пг.оегепцщегагог()7 Сопяо1е.игьсеъгпе("Отобразить информацию с помощью свойства Епсгу."); нн11е(есв.ночеиехс()) Сопяо1е.иг1яеъьпе(ест.кпсгу.Кеу + ": " + ест.Епсгу.Ча1це)) Сопяо1е.иггяеььпе(); Сопяо1е.иг11еъгпе("Отобразить информацню "с помощью свойств Кеу и Ча1це.")7 ег.г.кеяег()7 нк11е(ест.ноченехс()) сопяо1е.хг1гегьпе (егг.кеу + ": " + егг.ча1це) ( Ниже приведен результат выполнения этой программы.
Отобразить информацию с помощью свойства Епсгу. Мэри: 555-9876 Том: 555-3456 Толд: 555-3452 Кен: 555-7756 Отобразить информацию с помощью свойств Кеу и Ча1це. нери: 555-9876 Том: 555-3456 Толп: 555-3452 Кен: 555-7756 Реализация интерфейсов 1Епив(егаЬХе и ХЕпшпегагог Как упоминалось выше, для циклического обращения к элементам коллекции зачастую проще (да и лучше) организовать цикл Тогеасп, чем пользоваться непосредственно методами интерфейса 1Епцвегасог. Тем не менее ясное представление о принципе действия подобных интерфейсов важно иметь по еще одной причине: если требуется создать класс, содержащий объекты, перечисляемые в цикле Тогеасп, то в этом классе следует реализовать интерфейсы 1Епцвегасог и 1ЕпцвегаЬ1е.
Иными словами, для того чтобы обратиться к объекту определяемого пользователем класса в цикле Тогеасп, необходимо реализовать интерфейсы 1Епцвегасог и 1ЕпцвегаЬ1е в их обобщенной или необобщенной форме. Правда, сделать это будет нетрудно, поскольку оба интерфейса не очень велики. В приведенном ниже примере программы интерфейсы 1Епцвегагог и 1ЕпцвегаЬ1е реализуются в необобщенной форме, с тем чтобы перечислить содержимое массива, инкапсулированного в классе МуС1аяз.
О Реализовать интерфейсы ТЕпцщегаЬ1е и ТЕпщпегасог. ця1пч Зуясев( ця1пч Буясев.Со11есягопя; 1002 Часть [1. Библиотека С№ с1аяв МуС1аяя : 1Епцюегасог, 1ЕпцщегаЬ1е ( спаг[) спгя = ( 'А', 'В", 'С', 'Ь' гпс гбх = -1; // Реализовать интерфейс 1ЕпцщегаЬ1е. рцЬ1гс 1Епцщегаоог Оепкпцщегапог() гегцгп гпгяп В следующих методах реализуется интерфейс 1Епшпегатог // Возвратить текущий объект. рцЬ1гс оЬбесп Сцггепп ( п)ег [ гесцгп спгя[гбх)) ) // Перейти к след)чтпему объекту. рцЬ1гс Ьоо1 Мочеиехп() ( 1г"(1бх == спгя.ьепспп-1) ( невес()г // установить перечислитель в конец гегцгп Га1ве) ) гбх.н; геспгп Ггце; ) // установить перечиспитель в начало.
рцЬ11с чопб Ееяеп() ( 1бх = -1; ) ) с1аяя Епчщегапоггщр1оещо ( япапгс чоЫ Мафи() ( МуС1аяя щс = пен МуС1аяя() О Отобразить содержимое объекта щс. Гогеасп(спаг сп 1п щс) Сопяо1е.мгпсе(сп + " ")( Сопяо1е яггпеььпе () // Вновь отобразить содержимое объекта щс. Гогеасп(спаг сп гп щс) Сопяо1е.йг).те(сп + " "); Сопяо1е.иггсе1гпе() ) ) Зта программа дает следующий результат.