Г. Шилдт - Полный справочник по C# (1160789), страница 81
Текст из файла (страница 81)
Например, внашей программе при выполнении строкиI Count cdl = new Count(10);создается объект класса CountDown.Аддитивность пространств именВ одной программе одно и то же пространство имен можно объявить больше одного раза. Это позволяет распределить его по нескольким файлам или даже разделитьего внутри одного файла.
Например, в следующей программе определяется два пространства имен Counter. Одно содержит класс CountDown, второе — класс Countup.При компиляции содержимое двух пространств имен Counter объединяется в одно.Ill Демонстрация аддитивности пространств имен,using System;438Часть I. Язык С#// Делаем "видимым" пространство имен Counter,using Counter;// Теперь действующим является первое пространство// имен 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 v a l — ;else return 0;// Теперь действующим является второе пространство// имен Counter,namespace Counter {// Простой счетчик для счета в прямом направлении,class CountUp {int val;int target;public int Target {get{return target;public CountUp(int n) {target = n;val = 0;public void^ reset (int n) {target = n;val = 0;public int count() {if(val < target) return val++;else return target;class NSDemo {public static void Main() {Глава 16.
Пространства имен, препроцессор и компоновочные файлы439CountDown cd = new CountDown(10)CountUp cu = new CountUp(8);int i;do {i = cd.count();Console.Write (i + " " ) ;} while (i > 0 ) ;Console.WriteLine();do {i = cu.count();Console.Write(i + " " ) ;} while(i < cu.Target);1При выполнении этой программы получаем следующие результаты:10 9 8 7 6 5 4 3 2 1 00 1 2 3 4 5 6 7 8Хотелось бы обратить ваше внимание вот на что. ИнструкцияI using Counter;делает "видимым" содержимое обоих пространств имен. Поэтому к методамCountDown и CountUp можно обращаться напрямую, без уточняющей информации опространстве имен.
И тот факт, что пространство имен Counter было разделено надве части, не имеет никакого значения.Пространства имен могут быть вложеннымиОдно пространство имен можно вложить в другое. Рассмотрим следующую программу:// Демонстрация вложенных пространств имен.using System;namespace NS1 {class ClassA {public ClassA() {Console.WriteLine("Создание класса ClassA.");}}namespace NS2 { // Вложенное пространство имен,class ClassB {public ClassB() {Console.WriteLine("Создание класса ClassB.");c l a s s NestedNSDemo {p u b l i c s t a t i c v o i d Main() {N S 1 .
C l a s s A a= new N S 1 . C l a s s A ( ) ;// N S 2 . C l a s s B b = new N S 2 . C l a s s B ( ) ; // О ш и б к а ! ! !440Часть I. Язык С #// Пространство имен NS2 не находится в зоне видимости.NS1.NS2.ClassB b = new NS1.NS2.ClassB(); // Здесь все// правильно.IВот результаты выполнения этой программы:Создание класса ClassA.Создание класса ClassB.В этой программе пространство имен NS2 вложено в пространство имен NS1. Следовательно, при обращении к классу ClassB его имя необходимо уточнять, указываяоба пространства имен: как NS1, так и NS2.
Одного лишь имени NS2 недостаточно.Как видно в программе, имена пространств имен разделяются точкой.Вложенные пространства имен можно задавать с помощью одной инструкции, ноэазделив их точками. Например, задание вложенных пространств именnamespace OuterNS {namespace InnerNS {можно записать в таком виде:namespace OuterNS.InnerNS {Пространство имен по умолчаниюЕсли для программы не объявлено пространство имен, используется пространствоимен, действующее по умолчанию. Вот почему необязательно было указывать его дляпрограмм, приведенных в предыдущих главах.
Но если для коротких простых программ (подобных тем, что приведены в этой книге) такой стандартный подход вполнеприемлем (и даже удобен), большинство реальных программ содержится внутри некоторого пространства имен. Главная причина инкапсуляции программного кода внутрипространства имен состоит в предотвращении конфликтов при совпадении имен.Пространства имен — это еще один инструмент, позволяющий программисту так организовать свои программы, чтобы они не теряли жизнеспособности в сложной средес сетевой структурой.ПрепроцессорВ С# определен ряд директив препроцессора, которые влияют на способ интерпретации исходного кода компилятором. Эти директивы обрабатывают текст исходногофайла, в котором они находятся, еще до трансляции программы в объектный код.
Директивы препроцессора — в основном "выходцы" из C++, поскольку препроцессор• С# очень похож на тот, который определен в языке C++. Термин директива препроцессора своим происхождением обязан тому факту, что эти инструкции традиционнообрабатывались на отдельном этапе компиляции, именуемой процессором предварительной обработки, или препроцессором (preprocessor). Современная технология компиляторов больше не требует отдельного этапа для обработки директив препроцессором,но название осталось.Глава 16. Пространства имен, препроцессор и компоновочные файлы441В С# определены следующие директивы препроцессора:#define#elif#else#endif#endregion,terror#if#line#region#undef#warningВсе директивы препроцессора начинаются со знака " # " .
Кроме того, каждая директива препроцессора должна занимать отдельную строку.Откровенно говоря, поскольку в С# использована современная объектноориентированная архитектура, в директивах препроцессора программисты не испытывают острой необходимости, как это было в языках программирования более раннихпоколений. Тем не менее время от времени они могут быть полезными, особенно дляусловной компиляции. Рассмотрим все перечисленные выше директивы.# defineДиректива #def i n e определяет последовательность символов, именуемую идентификатором. С помощью директив # i f или # e l i f можно определить наличие или отсутствие в программе идентификатора, а результат такой проверки используется дляуправления компиляцией. Общая форма записи директивы #def i n e такова:#define идентификаторОбратите внимание на то, что в инструкции нет завершающей точки с запятой.Между самой директивой #def i n e и идентификатором может стоять любое количество пробелов, но завершить идентификатор можно только символом новой строки.Например, чтобы определить идентификатор EXPERIMENTAL, используйте следующуюдирективу:1 #define EXPERIMENTAL^SB^SSiilуДЁЗЗЗмШЗЗЦВ C/C++ директиву #define можно использовать для выполнения текстовыхподстановок, определяя для заданного значения осмысленное имя, а также дсоздания макросов, действующих подобно функциям.
Такое использование дрективы #define C# не поддерживает. В С# директива #define используется только для определения идентификатора.#if и #endifДирективы # i f и #endif позволяют выполнить условную компиляцию последовательности инструкций программного кода в зависимости от того, истинно ли выражение, включающее одно или несколько идентификаторов. Истинным считается идентификатор, определенный в программе.
В противном случае он считается ложным.Следовательно, если символ определен с помощью директивы #def ine, он оценивается как истинный.Общая форма использования директивы # i f такова:#if символьное_выражениепоследовательность_инструкций#endifЕсли выражение, стоящее после директивы # i f (символьное_выражение), истинно, код, расположенный между нею и директивой #endif(последовательно сть_инструкций), компилируется.
В противном случае он опускается. Директива#endif означает конец tif-блока.442Часть I. Язык С#Символьное выражение может состоять из одного идентификатора. Более сложноевыражение можно образовать с помощью следующих операторов: !, ==, !=, && и | |.Разрешено также использовать круглые скобки.Рассмотрим пример использования директив #if, #endif и #def ine.// Демонстрация использования директив #if, #endif// и tdefine.#define EXPERIMENTALusing System;class Test {public static void Main() {#if EXPERIMENTALConsole.WriteLine("Компилируется для экспериментальной версии.");#endifConsole.WriteLine("Эта информация отображается во всех версиях.");IПри выполнении программы отображаются следующие результаты:Компилируется для экспериментальной версии.Эта информация отображается во всех версиях.В этой программе с помощью директивы #define определяется идентификаторEXPERIMENTAL.
Поэтому при использовании директивы # i f символьное выражениеEXPERIMENTAL оценивается как истинное, и компилируется первая (из двух)WriteLine ()-инструкция. Если удалить определение идентификатора EXPERIMENTALи перекомпилировать программу, первая WriteLine ()-инструкция не скомпилируется, поскольку результат выполнения директивы # i f будет оценен как ложный.