1629295407-c61bfe4caba98380ea3e7cdae6295416 (846200), страница 79
Текст из файла (страница 79)
Класс CountKeys предназначен дляхранения текущего количества нажатых клавиш. В методе Main() создается объект классаKeyEvent. Затем создаются объекты классов ProcessKey и CountKeys, a ссылки на ихметоды keyhandler() добавляются в список вызовов, реализуемый с помощьюсобытийного объекта kevt.KeyPress.
Затем начинает работать цикл, в котором прикаждом нажатии клавиши вызывается метод kevt.OnKeyPress(), в результате чегозарегистрированные обработчики уведомляются о событии.430Часть I. Язык C#Полныйсправочник поГлава 16Пространства имен,препроцессор икомпоновочные файлыВэтой главе рассматриваются три C#-средства, которые позволяют влиять наорганизацию и доступность программы. Речь пойдет о пространствах имен,препроцессоре и компоновочных файлах.Пространства именО пространствах имен кратко упоминалось в главе 2, поскольку это одно изосновополагающих понятий C#: каждая C# -программа так или иначе использует некотороепространство имен.
До сих пор мы не затрагивали эту тему, поскольку C# автоматическипредоставляет программе пространство имен по умолчанию. Таким образом, программы,приведенные в предыдущих главах, просто использовали стандартное пространство имен.Но реальным программам придется создавать собственные или взаимодействовать сдругими пространствами имен. Поэтому настало время поговорить о них более подробно.Пространство имен определяет декларативную область, которая позволяет отдельнохранить множества имен. По существу, имена, объявленные в одном пространстве имен, небудут конфликтовать с такими же именами, объявленными в другом.
Библиотека .NETFramework (которая является C#-библиотекой) использует пространство имен System.Поэтому в начало каждой программы мы включали следующую инструкцию:using System;Как было показано в главе 14, классы ввода-вывода определяются внутрипространства имен, подчиненного System, и именуемого System.IO. Существуют идругие пространства имен, подчиненные System, которые включают иные части C#библиотеки.Возникновение пространств имен продиктовано самой жизнью, поскольку в течениепоследних лет для программирования характерен взрывоподобный рост количества именпеременных, методов, свойств и классов, которые используются в библиотечныхпроцедурах, приложениях сторонних изготовителей ПО и программах, написанныхотдельными программистами. Без использования пространств имен все эти имена боролисьбы за место “под солнцем” в глобальном пространстве имен, что привело бы к росту числаконфликтов.
Например, если в программе определяется класс Finder, это имя обязательнобудет конфликтовать с именем другого класса, Finder из библиотеки стороннегоприложения, которое использует ваша программа. К счастью, благодаря пространствамимен, проблем такого рода можно избежать, поскольку пространство имен локализуетвидимость имен, объявленных внутри него.Объявление пространства именПространство имен объявляется с помощью ключевого слова namespace. Общаяформа объявления пространства имен имеет следующий вид:namespace имя {// Члены}Здесь элемент имя означает имя пространства имен.
Все, что определено внутрипространства имен, находится в пределах его области видимости. Следовательно,пространство имен определяет область видимости. Внутри пространства имен можнообъявлять классы, структуры, делегаты, перечисления, интерфейсы или другоепространство имен.432Часть I. Язык C#Рассмотрим пример использования ключевого слова 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;}}Здесь класс CountDown объявляется внутри области видимости, определеннойпространством имен Counter.А теперь рассмотрим программу, которая демонстрирует использованиепространства имен Counter.// Демонстрация использования пространства имен.using System;// Объявляем пространство имен для счетчиков.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;}class NSDemo {public static void Main() {Counter.CountDown cd1 = new Counter.CountDown(10);int i;do {Глава 16.
Пространства имен, препроцессор и компоновочные файлы433}}i = cd1.count();Console.Write(i + "} while(i > 0);Console.WriteLine();Counter.CountDown cd2do {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();");= new Counter.CountDown(20);");");Вот результаты выполнения этой программы: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Здесь имеет смысл обратить ваше внимание вот на что.
Во-первых, поскольку классCountDown объявляется внутри пространства имен Counter, то при создании объектакласса CountDown, как показано в следующей инструкции, имя класса необходимоуказывать вместе с именем пространства имен Counter.Counter.CountDown cd1 = new Counter.CountDown(10);Но если объект Counter уже создан, то в дальнейшем называть его (или любой изего членов) полностью (по “имени-отчеству”) необязательно. Таким образом, методcd1.count() можно вызывать без указания имени пространства имен, как показано вэтой строке кода:i = cd1.count();Пространства имен предотвращают конфликты по совпадению именОсновное преимущество использования пространств имен состоит в том, что имена,объявленные внутри одного из них, не конфликтуют с такими же именами, объявленнымивне его. Например, в следующей программе создается еще один класс CountDown, но оннаходится в пространстве имен Counter2.// пространства имен предотвращают конфликты,// связанные с совпадением имен.using System;// Объявляем пространство имен для счетчиков.namespace Counter {// Простой счетчик для счета в обратном направлении.class CountDown {int val;public CountDown(int n) {val = n;434Часть I.
Язык C#}public void reset(int n) {val = n;}public int count() {if(val > 0) return val--;else return 0;}}}// Объявляем еще одно пространство имен.namespace Counter2 {/* Этот класс CountDown находится в пространствеимен Counter2 и не будет конфликтовать с одноименнымклассом, определенным в пространстве имен Counter. */}class CountDown {public void count() {Console.WriteLine("Этот метод count() находится в" +" пространстве имен Counter2.");}}class NSDemo {public static void Main() {// Этот класс CountDown находится в// пространстве имен Counter.Counter.CountDown cd1 = new Counter.CountDown(10);// Этот класс CountDown находится в// пространстве имен Counter2.Counter2.CountDown cd2 = new Counter2.CountDown();int i;}}do {i = cd1.count();Console.Write(i + " ");} while(i > 0);Console.WriteLine();cd2.count();Результаты выполнения этой программы имеют такой вид:10 9 8 7 6 5 4 3 2 1 0Этот метод count() находится в пространстве имен Counter2.Как подтверждают результаты выполнения этой программы, класс CountDownвнутри пространства имен Counter отделен от класса CountDown, определенного впространстве имен Counter2, и поэтому имена не конфликтуют.
Хотя этот пример оченьпростой, он позволяет понять, как избежать конфликтов при совпадении имен между своимкодом и кодом, написанным другими, поместив собственные классы в определенноепространство имен.Глава 16. Пространства имен, препроцессор и компоновочные файлы435Ключевое слово usingКак разъяснялось в главе 2, если программа включает часто встречающиеся ссылкина определенные члены пространства имен, то необходимость указывать имя этогопространства имен при каждом к ним обращении, очень скоро утомит вас. Эту проблемупозволяет решить директива using. В примерах этой книги использовалась директиваusing, чтобы сделать текущим C#-пространство имен System, поэтому вы уже с нимзнакомы.
Нетрудно предположить, что директиву using можно также использовать дляобъявления действующими пространств имен, создаваемых программистом.Существует две формы применения директивы using. Первая имеет такой вид:using имя;Здесь элемент имя означает имя пространства имен, к которому необходимополучить доступ. С этой формой директивы using вы уже знакомы. Все члены,определенные внутри заданного пространства имен, становятся частью этого (текущего)пространства имен, поэтому их можно использовать без дополнительного упоминания егоимени.
Директива using должна находиться в начале каждого программного файла, т.е.предшествовать всем остальным объявлениям.В следующей программе переработан пример использования счетчиков изпредыдущего раздела, чтобы показать, как с помощью директивы using можно чтобысделать текущим создаваемое программистом пространство имен.// Демонстрация использования пространства имен.using System;// Делаем текущим пространство имен Counter.using Counter;// Объявляем пространство имен для счетчиков.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;}class NSDemo {public static void Main() {// Теперь класс CountDown можно использовать// без указания имени пространства имен.CountDown cd1 = new CountDown(10);436Часть I.
Язык C#int i;do {i = cd1.count();Console.Write(i + " ");} while(i > 0);Console.WriteLine();CountDown cd2 = new 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();Эта программа иллюстрирует еще один важный момент: использование одногопространства имен не аннулирует другое.