Васильев А.Н. Основы программирования на C#. Васильев А. Н. Программирование
Скачать 5.54 Mb.
|
i НАЗ А МЕТКУ Мы продолжим наше знакомство с событиями, когда будем изучать методы создания приложений с графическим интерфейсом. Резюме Истинно вам говорю, 4 мая 1925 года Земля налетит на небесную ось. из к/ф Собачье сердце Делегат представляет собой тип данных, аналогичный классу. Экземпляр делегата является специальным объектом, который может ссылаться на методы. При описании делегата используется ключевое слово delegate , после которого указывается идентификатор типа результата метода, на который может ссылаться экземпляр делегата. Затем указывается имя делегата, ив круглых скобках описываются аргументы. Такие аргументы должны быть у метода, на который ссылается экземпляр делегата Создание экземпляра делегата напоминает создание обычного объекта. Объявляется переменная типа делегата, значением которой Делегаты и события 125 присваивается результат выражения на основе инструкции new и имени делегата со ссылкой на метод в круглых скобках. Также можно присвоить значением переменной типа делегата ссылки на метод Ссылка на нестатический метод выполняется так указывается имя объекта и через точку — имя метода. Ссылка на статический метод выполняется указанием названия класса и (через точку) имени метода Экземпляр делегата может ссылаться на несколько методов. Для добавления ссылки на метод (к уже существующим ссылкам в экземпляре делегата) используют оператор += (или операторы = и + ). Для удаления ссылки на метод из экземпляра делегата используют оператор (или операторы = и - ). • Экземпляр делегата можно вызывать. Для этого после имени экземпляра делегата (переменной, ссылающейся на экземпляр делегата) указываются круглые скобки и, если нужно, аргументы. Тип и количество аргументов определяются тем, как объявлен делегат, экземпляр которого вызывается. При этом с соответствующими аргументами будут вызваны все методы, на которые ссылается экземпляр делегата. Если вызываемые методы возвращают результат, то результатом выражения с вызовом экземпляра делегата является результат последнего вызванного метода Анонимный метод представляет собой блок кода, определяющий метод и предназначенный для присваивания в качестве значения переменной типа делегата. Анонимный метод описывается также, как обычный метод, но идентификатор типа результата не указывается, а вместо названия метода указывается ключевое слово delegate . Тип результата анонимного метода определяется типом результата, указанного в объявлении соответствующего делегата. Анонимный метод может содержать ссылки на внешние переменные Лямбда-выражения представляют собой альтернативу анонимным методам. Лямбда-выражение определяет метод и предназначено для присваивания в качестве значения переменной делегата. Лямб- да-выражение описывается подобно анонимному методу, но только ключевое слово delegate не используется, а между круглыми скобками с аргументами и телом описания метода размещается оператор. Существуют определенные правила, которые позволяют упростить синтаксис лямбда-выражений. Так, если аргумент один и его тип не указывается, то круглые скобки можно не использовать. При единственной команде в теле метода фигурные скобки можно Глава не использовать. Если в теле метода есть только одна команда с инструкцией, то инструкцию return можно не указывать Событие представляет собой автоматическое уведомление, посылаемое одним объектом прочим объектам. Событие реализуется с помощью специального члена класса. При объявлении события обычно указывается спецификатор доступа public , затем ключевое слово event , делегат и название события. Делегат, указанный в объявлении события, определяет сигнатуру методов, которые могут использоваться в качестве обработчиков события Для добавления в список обработчиков события ссылок на методы или экземпляры делегатов используется оператор += . Для удаления ссылок на методы и экземпляры делегатов из списка обработчиков события используют оператор -= . Событие, как и экземпляр делегата, может быть вызвано (сгенерировано), но это можно сделать только в пределах кода класса. Для генерирования события после имени события указываются круглые скобки с аргументами. Количество и тип аргументов определяются делегатом, указанным при объявлении события. При генерировании события автоматически вызываются все методы и экземпляры делегата, зарегистрированные в качестве обработчиков для данного события Хотя событие напоминает экземпляр делегата, между ними существует разница — примерно такая, как между свойством и полем. С каждым событием связано два метода-аксессора. При добавлении с помощью оператора += ) ссылки на метод в список обработчиков события вызывается add -аксессор. При удалении (с помощью метода) ссылки на метод из списка обработчиков события вызывается remove -аксессор. Эти аксессоры можно описать в явном виде при объявлении события. Задания для самостоятельной работы Отведай ты из моего кубка. из к/ф Иван Васильевич меняет профессию Напишите программу, в которой объявляется делегат для методов с двумя аргументами (символ и текст) и целочисленным результатом. В главном классе необходимо описать два статических метода. Один Делегаты и события 127 статический метод результатом возвращает количество вхождений символа (первый аргумент) в текстовую строку (второй аргумент. Другой метод результатом возвращает индекс первого вхождения символа (первый аргумент) в текстовую строку (второй аргумент) или значение -1, если символ в текстовой строке не встречается. В главном методе создать экземпляр делегата и с помощью этого экземпляра вызвать каждый из статических методов Напишите программу, в которой объявляется делегат для методов с символьным аргументом, не возвращающих результат. Опишите класс, в котором должно быть символьное поле и метод, позволяющий присвоить значение символьному полю объекта. У метода один символьный аргумент, и метод не возвращает результат. Создайте массив объектов данного класса. Создайте экземпляр делегата. В список вызовов этого делегата необходимо добавить ссылки на метод (присваивающий значение символьному полю) каждого объекта из массива. Проверьте результат вызова такого экземпляра делегата Напишите программу, в которой объявлен делегат, предназначенный для работы с методами, не имеющими аргумента и возвращающими символьный результат. Опишите классу которого есть текстовое поле, а также закрытое поле, являющееся ссылкой на экземпляр делегата. В классе нужно описать открытое свойство, доступное только для чтения. Значением свойства является значение закрытого поля (то есть ссылка на экземпляр делегата. Опишите конструктор класса с двумя аргументами текстовым (тип string) и логическим (тип bool). Первый текстовый аргумент определяет значение текстового поля объекта, а второй логический аргумент определяет значение закрытого поля типа делегата. Если второй аргумент истинный, то закрытому полю значением присваивается анонимный метод (или лямбда-выражение), возвращающий результатом первый символ из текстового поля. Если логический аргумент ложный, то закрытому полю значением присваивается анонимный метод (или лямбда выражение, возвращающий результатом последний символ из текстового поля. Создайте объекты класса и проверьте функциональность свойства его можно вызывать как метод, без аргументов, а результатом является первый или последний символ в текстовом поле (в зависимости оттого, с каким логическим аргументом создавался объект Напишите программу, в которой объявляется делегат для работы с методами, имеющими целочисленный аргумент и целочисленный Глава результат. Опишите класс с индексатором (доступен только для считывания значения. Индексатор результатом должен возвращать ссылку на экземпляр делегата. Экземпляр делегата ссылается на методу которого целочисленный аргумент. Результатом метод возвращает целочисленное значение, получающееся возведением аргумента метода в степень, определяемую индексом объекта. Общий эффект такой если некоторый объект obj класса проиндексировать с неотрицательным индексом k ив круглых скобках указать аргумент n (команда вида obj[k](n)), то результатом такого выражения должно быть значение n в степени k. 5. Напишите программу, в которой с помощью делегатов и анонимных методов (лямбда-выражений) создается экземпляр делегата, который вызывается без аргументов, а результатом возвращает число из последовательности Фибоначчи — при каждом новом вызове получаем новое число в последовательности. В последовательности Фибоначчи первые два числа равны единице, а каждое следующее число равно сумме двух предыдущих Напишите программу, в которой с помощью делегатов и анонимных методов (лямбда-выражений) создается экземпляр делегата, который вызывается без аргументов, а результатом возвращает текстовое значение с названием дня недели ( ƎɉɨɧɟɞɟɥɶɧɢɤƎ, ƎȼɬɨɪɧɢɤƎ итак до ƎȼɨɫɤɪɟɫɟɧɶɹƎ). При каждом новом вызове экземпляра результатом возвращается название следующего дня недели. После Ǝȼɨɫɤɪɟɫɟ- ɧɶɹƎ результатом возвращается ƎɉɨɧɟɞɟɥɶɧɢɤƎ итак далее Напишите программу, содержащую статический метод. Первым аргументом статическому методу передается целочисленный массив. Вторым аргументом статическому методу передается ссылка на другой метод. У метода-аргумента должен быть целочисленный аргумент, ион должен возвращать целочисленный результат. Результатом статический метод возвращает целочисленный массив. Элементы этого массива вычисляются как результат вызова метода-аргумента, если ему передавать значения элементов из массива-аргумента. Предложите механизм проверки функциональности данного статического метода Напишите программу, в которой объявлен делегат, соответствующий методам с целочисленным аргументом и целочисленным результатом. Необходимо описать статический метод с двумя аргументами, каждый из которых является ссылкой на экземпляр делегата (ссылка на метод. Результатом статического метода также является ссылка на экземпляр Делегаты и события делегата. Статический метод работает по такой схеме при вызове ему передаются ссылки на два метода (методы-аргументы), а результатом статический метод возвращает ссылку на метод (метод-результат). Действие метода-результата на свой аргумент эквивалентно последовательному применению к этому аргументу методов-аргументов. Другими словами, если аргументами статическому методу передаются ссылки f и h на некоторые методы, то результатом является ссылка на метод, который для аргумента n вычисляет значение f(h(n)). Предложите механизм проверки функциональности статического метода Напишите программу, содержащую статический метод стремя действительными (тип double) аргументами. Результатом статического метода является ссылка на метод, вычисляющий квадратичный трехчлен с коэффициентами, определяемыми аргументами статического метода. Другими словами, если статический метод вызывается с числовыми аргументами a, b и c, то результатом является ссылка на метод, который для аргумента x типа double результатом вычисляет значение выражения a*x*x+b*x+c. 10. Напишите программу, в которой есть класс с событием. Событие обрабатывается методами, имеющими текстовый аргумент и не возвращающими результат. У класса должно быть текстовое поле, в которое при создании объекта класса записывается название объекта. В классе должен быть описан метод для генерирования события, который вызывается без аргументов. При генерировании события аргументом передается значение текстового поля объекта, генерирующего событие. Еще один класс, описанный в программе, должен содержать метод с текстовым аргументом, не возвращающий результат. При вызове метод отображает значение своего текстового аргумента. В главном методе программы необходимо создать два объекта первого класса и один объект второго класса. Для событий объектов первого класса обработчиком регистрируется метод объекта второго класса (получается, что метод одного итого же объекта зарегистрирован обработчиком для событий двух объектов. Для каждого из объектов первого класса необходимо сгене- рировать событие. При этом метод, зарегистрированный обработчиком, должен выводить название объекта, сгенерировавшего событие Глава ПЕРЕЧИСЛЕНИЯ И СТРУКТУРЫ Вы напрасно, господа, ходите без калош. Во-первых, вы простудитесь. А во-вторых, вы наследите мне на коврах. А все ковры у меня персидские. из к/ф Собачье сердце» В этой главе мы познакомимся с перечислениями и структурами узнаем, что это такое и как используется. После изучения материала главы мы будем знать как описывается перечисление как создается и используется переменная типа перечисления как описывается структура чем структура отличается от класса как создается экземпляр структуры какие операции могут выполняться с экземплярами структуры. Все вопросы и темы, рассматриваемые в главе, подкрепляются приме- рами. Знакомство с перечислениями Владимир Николаевич, человечество из-за одного камушка с Луны тысячелетия потратило, а тут живой инопланетянин и эцих из неизвестного металла! из к/ф «Кин-дза-дза» Перечисление — это тип данных, определяемый пользователем. Переменная, объявленная как относящаяся к типу перечисления, может Перечисления и структуры 131 принимать значение одной из целочисленных констант. Список этих констант фактически детерминирует (определяет) перечисление как тип НАЗ А МЕТКУ Другими словами, имеется набор целочисленных констант и переменная может принимать значение одной из этих констант. Набор констант формирует тип, к которому относится соответствующая переменная. Такой тип называется перечислением. Таким образом, определяя перечисление как тип данных, мы задаем набор значений, которые может принимать переменная, относящаяся к данному типу. Значения, входящие в набор, целочисленные (по умолчанию типа int), но каждое имеет свое уникальное имя (то есть является константой). Для использования перечисления в программе мы должны сначала описать тип перечисления. После того как тип определен, его можно использовать (в качестве типа переменных, например. Ниже приведен шаблон для объявления перечисления ɢɦɹ Начинается все с ключевого слова enum. Оно является индикатором того, что объявляется именно перечисление. После ключевого слова enum указывают перечисления, которое фактически представляет собой название создаваемого типа. Именно ɢɦɹ перечисления используется как идентификатор типа данных при объявлении переменных. После имени перечисления в фигурных скобках через запятую перечисляются названия ɤɨɧɫɬɚɧɬ. Константы, формирующие тип перечисления, предварительно объявлять ненужно. То есть, когда мы в списке перечисляем названия констант, тотем самым мы их объявляем (и инициализируем. По умолчанию первая константа в списке получает значение 0, вторая константа в списке получает значение 1, итак далее значение каждой следующей константы на единицу больше ее предшественницы. Допустим, в программе при объявлении перечисления использована следующая команда Animals Этой командой определяется перечисление Animals. Впоследствии идентификатор Animals мы сможем использовать как обозначение для Глава типа данных. Например, мы сможем объявить переменную, относящуюся к типу перечисления Animals: Animals Объявленная таким образом переменная animal относится к типу Animals , и это означает, что значением переменной может быть одна из констант, формирующих тип Animals (имеются ввиду константы Cat , Dog, Fox, Wolf и Bear). Напомним, что константы, формирующие перечисление, являются целочисленными. Их значения — целые числа. В данном случае значение первой в списке {Cat,Dog,Fox,Wolf,Bear} константы Cat равно 0, значение константы Dog равно 1, итак далее — последняя (пятая по счету) в списке константа Bear имеет значение 4. Константы из списка получают эти значения автоматически. Следует учесть, что константы из списка, определяющего перечисление, несколько отличаются от обычных констант, объявленных в индивидуальном порядке. Константы из списка перечисления используются с указанием имени перечисления. Ниже приведена команда, которой присваивается значение переменной Переменной animal присваивается значением константа Cat, причем ссылка на эту константу выполнена как Animals.Cat. То есть сначала указывается имя перечисления Animals и через точку — название константы из этого перечисления. Это стандартный способ обращения к константам из перечисления имени константы предшествует имя перечисления, и разделяются они точкой ПОДРОБНОСТИ bХотя константы из перечисления технически реализуются как целочисленные значения, автоматического преобразования между целочисленными значениями и значениями типа перечисления нет. Обычно приходится выполнять явное приведение типов. Используемый по умолчанию для реализации значений из перечисления тип int можно заменить на другой целочисленный тип. Для этого идентификатор базового типа указывается через двоеточие после названия перечисления, как показано ниже ɢɦɹ: ɬɢɩ {ɤɨɧɫɬɚɧɬɚ,ɤɨɧɫɬɚɧɬɚ,...,ɤɨɧɫɬɚɧɬɚ}; Перечисления и структуры 133 Например, для того чтобы базовым при реализации значений типа перечисления был типа не тип int, можем использовать такое объявление для перечисления Animals: enum Animals: byte Также мы можем явно инициализировать константы, формирующие перечисления. В таком случае после имени константы указывается оператор присваивания = и значение константы. Причем необязательно явно указывать значение для всех констант перечисления. Разрешается указать значения только некоторых констант. В таком случае для констант, значение которых явно не указано, действует прежнее правило значение очередной константы на единицу больше значения предыдущей константы. Допустим, перечисление объявлено с помощью такой команды Animals: byte В этом случае константа Cat реализуется с целочисленным значением 0, константа Dog реализуется со значением 1, константа Fox реализуется со значением 100, значение константы Wolf равно 101, а значение константы равно 200. Небольшая программа, в которой используются перечисления, представлена в листинге 3.1. Листинг 3.1. Знакомство с перечислениями System; // Ɉɛɴɹɜɥɟɧɢɟ ɩɟɪɟɱɢɫɥɟɧɢɹ: enum Animals {Cat,Dog,Fox,Wolf,Bear}; // Ɉɛɴɹɜɥɟɧɢɟ ɩɟɪɟɱɢɫɥɟɧɢɹ ɫ ɢɧɢɰɢɚɥɢɡɚɰɢɟɣ ɤɨɧɫɬɚɧɬ: enum Coins {One=1,Two,Five=5,Ten=10,Fifty=50}; // Ʉɥɚɫɫ ɫ ɝɥɚɜɧɵɦ ɦɟɬɨɞɨɦ: class EnumDemo{ // Ƚɥɚɜɧɵɣ ɦɟɬɨɞ: static void Main(){ Console.WriteLine( Ǝȼ ɦɢɪɟ ɠɢɜɨɬɧɵɯƎ); // ɉɟɪɟɦɟɧɧɚɹ ɬɢɩɚ ɩɟɪɟɱɢɫɥɟɧɢɹ: Animals animal=Animals.Cat; Console.WriteLine( Ǝanimal: {0,-5} ɢɥɢ {1}Ǝ,animal,(int)animal); Глава 3 |