Г. Шилдт - С#4.0 Полное руководство (1160795), страница 90
Текст из файла (страница 90)
Меяяаде); г = 0.01 ) сассЬ(очегт1онвхсерсгоп ехс) ( Сопяо1е.Хг1севдпе(ехс.Меяяаде); с=О; ) яоя += и; ) анд = яоя / и; сопяо1е.игггеьгпе("среднее равно " + ачд); ) ) 472 Часть (. Язык С(г Выполнение этой программы может привести, например, к следующему результату. Сколько чисел вы собираетесь ввести: 5 введите 5 чисел. 1.1 2.2 з.з 4.4 5.5 Среднее равно З.З Следует особо подчеркнуть, что для каждого преобразуемого значения необходимо выбирать подходящий метод синтаксического анализа. Так, если попытаться преобразовать строку, содержащую значение с плавающей точкой, методом 1ЬС32.
Расее (), то искомый результат, т.е. числовое значение с плавающей точкой, получить не удастся. Как пояснялось выше, при неудачном исходе преобразования метод Расее () сгенерирует исключение. Длл того чтобы избежать генерирования исключений при преобразовании числовых строк, можно воспользоваться методом ТгуРагве (), определенным для всех числовых структур. В качестве примера ниже приведен один из вариантов метода Тгуралае (), определяемых в структуре 1ЬС32: ягаоьс Ьоо1 тлуратве(влтглЧ в, оол Тлс результат) где в обозначает числовую строку, передаваемую данному методу, который возвращает соответствующий результат после преобразования с учетом выбираемой по умолчанию местной специфики представления чисел.
(Конкретную местную специфику представления чисел с учетом региональных стандартов можно указать в другом варианте данного метода.) При неудачном исходе преобразования, например, когда параметр в не содержит числовую строку в надлежащей форме, метод Тгурагяе () возвращает логическое значение Та1ве.
В противном случае он возвращает логическое значение слое. Следовательно, значение, возвращаемое этим методом, обязательно следует проверить, чтобы убедиться в удачном (или неудачном) исходе преобразования. 474 Часть (. Язык С№ Следует особо подчеркнуть, что один и тот же делегат может быть использован для вызова разных методов во время выполнения программы, для чего достаточно изменить метод, на который ссылается делегат. Таким образом, метод вызываемый делегатом, определяется во время выполнения, а не в процессе компиляции. В этом, собственно, и заключается главное преимущество делегата.
ПРИМЕЧАНИЕ Если у аас имеется опыт программирования иа С/С++, то вам полезно будет знать, что делегат в С№ подобен указателю на функцию в С/С++. Тип делегата объявляется с помощью ключевого слова с(е1едаге. Ниже приведена общая форма объявления делегата: с)е1едаге воэвращаемый тип имя(список параметров) где возвращаемый тип обозначает тип значения, возвращаемого методами, которые будут вызываться делегатом; имя — конкретное имя делегата; список параметров— параметры, необходимые для методов, вызываемых делегатом. Как только будет создан экземпллр делегата, он может вызывать и ссылаться на те методы, возвращаемый тип и параметры которых соответствуют указанным в объявлении делегата.
Самое главное, что делегат может служить для вызова любого метода с соответствующей сигнатурой и возвращаемым типом. Более того, вызываемый метод может быть методом экземпляра, связанным с отдельным объектом, или же статическим методом, связанным с конкретным классом. Значение имеет лишь одно: возвращаемый тип и сигнатура метода должны быть согласованы с теми, которые указаны в объявлении делегата. Для того чтобы показать делегат в действии, рассмотрим для начала простой пример его применения. Простой пример применения делегата.
пяьпд Яуясеи; // Объявить тип делегата. бе1едаье ятг1пд Япгиоб(яггьпд япг); с1аяя Ое1едаьетеяь ( // Заменить пробелы дефисами. вьапьс впгьпд Пер1асезрасея(япгьпд я) Сопяо1е.нг1пеььпе("Замена пробелов дефисами."); гегпгп в.пер1асе(' ', '-'): Удалить пробелы. воапьс яьгьпд яеиотеЯрасев(ягггпд я) ( ясг1пд сеир дпг 1; Сопво1е.
Иль теььпе (" Удаление пробелов. " ) гол(1=0; 1 < в.ьепдс)1г 1ьь) 11(в(1) != ' ') Севр т= в(1]; Глава 15. Делегаты, события и лямбда-выражения 475 геспгп Сещр) ) /! Обратить -строку. ясаггс яггфпч Вечегяе(всгтпч я) ( ягг1пд геюр = 1пг 1, Сопяо1е.иг1веьгпе("Обращение строки.")у Рог(О=О, 1=в.Велдона-1) 1 >= О; 1 †, 1++) гещр += в(г); гегпгп Сещр) ) всасгс чогд Магп() ( // Сконструировать делегат. ЯягМод астор = пеи Ясгмод(аер1всеврвсея)р ягг1по ягг; !/ Вызвать методы с помощью делегата. всг = астор("Это простой тест."); Сопяо1е.нггсевапе("Результирующая строка: " + всг) Сопяо1е.игтсе11пе(); всгор = пен ЯсгМод(яеюочеЯрасея); вгг = яггор("Это простой тест."); сопяо1е.хгггеьтпе("Результирующая строка: " + ягг) Сопво1е.нгтсеьтпе(); всгор пеи Ясгнод(вечегве)) ясг = вггор("это простой тест."); Сопяо1е.Хггсеьдпе("Результирующая строка: " + ясг) Вот к какому результату приводит выгголнение этого кода.
Замена пробелов дефисами. Результирующая строка: Это-простой-тест. Удаление пробелов. Результирующая строка: Этопростойтест. Обращение строки. Результирующая строка: .тсет йотсорп отЭ Рассмотрим данный пример более подробно. В его коде сначала объявляется делегат Бтгыод типа ятг1пд, как показано ниже. де1едаге ясгтпд Ясгиод(всг1по всг) Как видите, делегат Бтгмод принимает один параметр типа зсг1пд и возвращает одно значение того же типа.
476 Часть ). Язык С() Далее в классе Ое1едагетевб объявляются три статических метода с одним параметром типа в с г1пп и возвращаемым значением того же типа. Следовательно, они соответствуют делегату БС гмоб. Эти методы видоизменяют строку в той или иной форме. Обратите внимание на то, что в методе Вер1асеБрасев () для замены пробелов дефисами используется один из методов типа вгг1пс — Вер1асе () . В методе Маап () создается переменная экземпляра вггОр ссылочного типа Бггмос) и затем ей присваивается ссылка на метод Вер1асеБрасев () .
Обратите особое внимание на следующую строку кода. Бггноо вггор = пеи Бггиог)(яер1асезрасев) В этой строке метод Вер1асеэрасев () передается в качестве параметра. При этом указываетог только его имя, но не параметры. Данный пример можно обобщить: при получении экземпляра делегата достаточно указать только имя метода, на который должен ссылаться делегат. Ясно, что сигнатура метода должна совпадать с той, что указана в объявлении делегата.
В противном случае во время компиляции возникнет ошибка. Далее метод Вер1асеБрасев () вызывается с помощью экземпляра делегата втгор, как показано ниже. вгг = вггор("Это простой тест."); Экземпляр делегата в Стор ссылается на метод Вер1асе Бра се в ( ), и поэтому вызывается именно этот метод. Затем экземпляру делегата в С гОр присваивается ссылка на метод Вещоче эра се в ( ), и с его помощью вновь вызывается указанный метод — на этот раз Вещочеэрасев () . И наконец, экземпляру делегата в С гор присваивается ссылка на метод Вече две ( ) . А в итоге вызывается именно этот метод.
Главный вывод из данного примера заключается в следующем: в тот момент, когда происходит обращение к экземпляру делегата вбгор, вызывается метод, на который он ссылается. Следовательно, вызов метода разрешается во время выполнения, а не в процессе компиляции.
Групповое преобразование делегируемых методов Еще в версии С() 2.0 было внедрено специальное средство, существенно упрощающее синтаксис присваивания метода делегату. Это так называемое групповог преобразование методов, позволяющее присвоить имя метода делегату, не прибегая к оператору пеи или явному вызову конструктора делегата. Ниже приведен метод Маап () из предыдущего примера, измененный с целью продемонстрировать групповое преобразование методов.
вгатьс чего Маьп() ( Сконструировать делегат, используя групповое преобразование методов. Бсгмог) астор = Вер1асезрасев; // использовать групповое преобразование методов всг1пд всгг Вызвать методы с помощью делегата. вгг = вггор("Это простой тест."); сопво1е.хггсеыпе("Результирующая строка: " + всг) Сопво1е.мгггеЫпе М; Глава 1б. Делегаты, события и лямбда-выражения 477 астор = Яешоуезраоев( // использовать групповое преобразование методов всг = астор("Это простой тест."); Сопво1е.иггсет ьпе("Результирующая строка: " + всг); Сопво1е.иггтетьпе()( астор .= Яеуегве; !Г использовать групповое преобразование методов всг = астор("Зто простой тест."); сопво1е.хгггеьгпе("Результируюшая строка: " т вгг)т Сопво1е.Хггсе) ьпе(); ) Обратите особое внимание на то, как создается экземпляр делегата з Стор и как ему присваивается метод Нер1асеэрасев в следующей строке кода.
вггор = Кешоуезрасевг // использовать групповое преобразование методов В этой строке кода имя метода присваивается непосредственно экземпляру делегата з с гор, а все заботы по автоматическому преобразованию метода в тип делегата "возлагаются" на средства С(). Этот синтаксис может быть распространен на любую ситуацию, в которой метод присваивается или преобразуется в тип делегата. Синтаксис группового преобразования методов существенно упрощен по сравнению с прежним подходом к делегированию, поэтому в остальной части книги используется именно он.
Применение методов экземпляра в качестве делегатов В предыдущем примере использовались статические методы, но делегат может ссылаться и на методы экземпляра, хотя для этого требуется ссылка на объект. Так, ниже приведен измененный вариант предыдущего примера, в котором операции со строками инкапсулируются в классе Ясг1пгторз.