Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
Вот, например, к какому результату приводит выполнение этой программы.Введите несколько символов. По завершении введите точку.t Получено сообщение о нажатии клавиши: tе Получено сообщение о нажатии клавиши: еs Получено сообщение о нажатии клавиши: st Получено сообщение о нажатии клавиши: t. Получено сообщение о нажатии клавиши: .Было нажато 5 клавиш.
В самом начале этой программы объявляется класс KeyEventArgs, производныйот класса EventArgs и служащий для передачи сообщения о нажатии клавиши обработчику событий. Затем объявляется обобщенный делегат EventHandler, определяющий обработчик событий, связанных с нажатием клавиш. Эти события инкапсулируются в классе KeyEvent, где определяется событие KeyPress.
В методе Main() сначала создается объект kevt класса KeyEvent. Затем в цепочку событий kevt.KeyPress добавляется обработчик, предоставляемый лямбда-выражением. В этом обработчике отображается факт каждого нажатия клавиши, какпоказано ниже.kevt.KeyPress += (sender, е) => Console.WriteLine(" Получено сообщение о нажатии клавиши: " + e.ch);
Далее в цепочку событий kevt.KeyPress добавляется еще один обработчик, предоставляемый лямбда-выражением. В этом обработчике подсчитывается количествонажатых клавиш, как показано ниже.kevt.KeyPress += (sender, е) => count++; // count — это внешняя переменная
Обратите внимание на то, что count является локальной переменной, объявленнойв методе Main() и инициализированной нулевым значением.
Далее начинает выполняться цикл, в котором метод kevt.OnKeyPress() вызывается при нажатии клавиши. Об этом событии уведомляются все зарегистрированныеобработчики событий. По окончании цикла отображается количество нажатых клавиш. Несмотря на всю свою простоту, данный пример наглядно демонстрирует самусуть обработки событий средствами С#. Аналогичный подход может быть использовани для обработки других событий. Безусловно, в некоторых случаях анонимные обработчики событий могут оказаться непригодными, и тогда придется внедрить именованные методы.
ГЛАВА 16. Пространства имен, препроцессор и сборки
В этой главе речь пойдет о трех средствах С#, позволяющих улучшить организованность и доступность программы. Этими средствами являются пространстваимен, препроцессор и сборки.Пространства имен
О пространстве имен уже вкратце упоминалось в главе 2в связи с тем, что это основополагающее понятие для С#.В действительности пространство имен в той или иной степени используется в каждой программе на С#. Потребностьв подробном рассмотрении пространств имен не возникаладо сих пор потому, что для каждой программы на C# автоматически предоставляется используемое по умолчаниюглобальное пространство имен. Следовательно, в примерах программ, представленных в предыдущих главах, использовалось глобальное пространство имен. Но во многихреальных программах приходится создавать собственныепространства имен или же организовать взаимодействиес другими пространствами имен. Подобные пространствабудут представлены далее во всех подробностях.
Пространство имен определяет область объявлений,в которой допускается хранить одно множество имен отдельно от другого. По существу, имена, объявленныев одном пространстве имен, не будут вступать в конфликтс аналогичными именами, объявленными в другой области. Так, в библиотеке классов для среды .NET Framework,которая одновременно является библиотекой классов С#,используется пространство имен System. Именно поэтомустрока кодаusing System;
обычно вводится в самом начале любой программы на С#. Как пояснялось в главе 14,классы ввода-вывода определены в пространстве имен System.IO, подчиненном пространству имен System. Ему подчинены и многие другие пространства имен, относящиеся к разным частям библиотеки классов С#.
Пространства имен важны потому, что за последние годы в программировании"расплодились" в огромном количестве имена переменных, методов, свойств и классов, применяемых в библиотечных программах, стороннем и собственном коде. Поэтому без отдельных пространств все эти имена будут соперничать за место в глобальномпространстве имен, порождая конфликтные ситуации. Так, если в программе определен класс Finder, то этот класс может вступить в конфликт с другим классом Finder,доступным в сторонней библиотеке, используемой в этой программе. К счастью, подобного конфликта можно избежать, используя отдельные пространства имен, ограничивающие область видимости объявленных в них имен.Объявление пространства имен
Пространство имен объявляется с помощью ключевого слова namespace. Нижеприведена общая форма объявления пространства имен:namespace имя { // члены}
где имя обозначает конкретное имя объявляемого пространства имен. При объявлениипространства имен определяется область его действия. Все, что объявляется непосредственно в этом пространстве, оказывается в пределах его области действия. В пространстве имен можно объявить классы, структуры, делегаты, перечисления, интерфейсыили другие пространства имен.
Ниже приведен пример объявления namespace для создания пространства именCounter. В этом пространстве локализуется имя, используемое для реализации простого класса вычитающего счетчика CountDown.// Объявить пространство имен для счетчиков.namespace Counter { // Простой вычитающий счетчик. class CountDown { int val; public CountDown(int n) { val = n; } public void Reset(int n) { val = n; } public int Count() { if(val > 0) return val--; else return 0; } }} // Это конец пространства имен Counter.
Обратите внимание на то, что класс CountDown объявляется в пределах областидействия пространства имен Counter. Для того чтобы проработать этот пример напрактике, поместите приведенный выше код в файл Counter.cs.
Ниже приведен пример программы, демонстрирующий применение пространстваимен Counter.// Продемонстрировать применение пространства имен Counter.using System;class NSDemo { static void Main() { // Обратите внимание на то, как класс CountDown // определяется с помощью пространства имен Counter. Counter.CountDown cd1 = new Counter.CountDown(10); int i; do { i = cd1.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); // Еще раз обратите внимание на то, как класс CountDown // определяется с помощью пространства имен Counter. Counter.CountDown cd2 = new Counter.CountDown(20); do { i = cd2.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); cd2.Reset(4); do { i = cd2.Count(); Console.Write(i + " "); } while(i > 0); Console.WriteLine(); }}
При выполнении этой программы получается следующий результат.10 9 8 7 6 5 4 3 2 1 020 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 04 3 2 1 0
Для того чтобы скомпилировать эту программу, вы должны включить приведенный выше код в отдельный файл и указать его вместе с упоминавшимся вышефайлом, содержащим код объявления пространства имен Counter. Если этот коднаходится в файле NSDemo.cs, а код объявления пространства имен Counter — в файле Counter.cs, то для компиляции программы используется следующая команднаястрока.csc NSDemo.cs counter.cs
Некоторые важные аспекты данной программы заслуживают более пристальноговнимания. Во-первых, при создании объекта класса CountDown необходимо дополнительно определить его имя с помощью пространства имен Counter, как показанониже. Ведь класс CountDown объявлен в пространстве имен Counter.Counter.CountDown cd1 = new Counter.CountDown(10);
Это правило можно обобщить: всякий раз, когда используется член пространстваимен, его имя необходимо дополнительно определить с помощью этого пространстваимен. В противном случае член пространства имен не будет обнаружен компилятором.
Во-вторых, как только объект типа Counter будет создан, дополнительно определять его члены с помощью пространства имен уже не придется. Следовательно, методcd1.Count() может быть вызван непосредственно без дополнительного указания пространства имен, как в приведенной ниже строке кода.i = cd1.Count();