Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
В этом варианте программы для класса Counter сначала указывается псевдонимCtr в следующей строке кода.using Ctr = Counter;
А затем этот псевдоним используется в методе Main() для дополнительного описания класса CountDown, как показано ниже.Ctr::CountDown cd1 = new Ctr::CountDown(10);
Описатель :: устраняет неоднозначность, поскольку он явно указывает на то, чтоследует обратиться к классу CountDown из пространства Ctr, а фактически — Counter.Именно это и делает теперь программу пригодной для компиляции.
Описатель :: можно также использовать вместе с предопределенным идентификатором global для ссылки на глобальное пространство имен. Например, в приведенной ниже программе класс CountDown объявляется как в пространстве имен Counter,так и в глобальном пространстве имен. А для доступа к варианту класса CountDown вглобальном пространстве имен служит предопределенный псевдоним global.// Использовать псевдоним глобального пространства имен.using System;// Присвоить классу Counter псевдоним Ctr.using Ctr = Counter;// Объявить пространство имен для счетчиков.namespace Counter {// Простой вычитающий счетчик. class CountDown { int val; public CountDown(int n) { val = n; } // ... }}// Объявить еще один класс CountDown, принадлежащий// глобальному пространству имен.class CountDown { int val; public CountDown(int n) { val = n; } // ...}class GlobalAliasQualifierDemo { static void Main() { // Здесь описатель :: предписывает компилятору использовать // класс CountDown из пространства имен Counter. Ctr::CountDown cd1 = new Ctr::CountDown(10); // Далее создать объект класса CountDown из // глобального пространства имен. global::CountDown cd2 = new global::CountDown(10); // ... }}
Обратите внимание на то, что идентификатор global служит для доступа к классуCountDown из используемого по умолчанию пространства имен.global::CountDown cd2 = new global::CountDown(10);
Этот подход можно распространить на любую ситуацию, в которой требуется указывать используемое по умолчанию пространство имен.
И последнее: описатель псевдонима пространства имен можно применять вместе спсевдонимами типа extern, как будет показано в главе 20.Препроцессор
В С# определен ряд директив препроцессора, оказывающих влияние на интерпретацию исходного кода программы компилятором. Эти директивы определяют порядок интерпретации текста программы перед ее трансляцией в объектный код в томисходном файле, где они появляются. Термин директива препроцессора появился в связис тем, что подобные инструкции по традиции обрабатывались на отдельной стадиикомпиляции, называемой препроцессором. Обрабатывать директивы на отдельной стадии препроцессора в современных компиляторах уже не нужно, но само ее названиезакрепилось.
Ниже приведены директивы препроцессора, определенные в С#.#define#elif#else#endif#endregion#error#if#line#pragma#region#undef#warning
Все директивы препроцессора начинаются со знака #. Кроме того, каждая директива препроцессора должна быть выделена в отдельную строку кода.
Принимая во внимание современную объектно-ориентированную архитектуруязыка С#, потребность в директивах препроцессора в нем не столь велика, как в языкахпрограммирования предыдущих поколений. Тем не менее они могут быть иногда полезными, особенно для условной компиляции. В этом разделе все директивы препроцессора рассматриваются по очереди.Директива #define
Директива #define определяет последовательность символов, называемую идентификатором. Присутствие или отсутствие идентификатора может быть определено спомощью директивы #if или #elif и поэтому используется для управления процессом компиляции. Ниже приведена общая форма директивы #define.#define идентификатор
Обратите внимание на отсутствие точки с запятой в конце этого оператора. Междудирективой #define и идентификатором может быть любое количество пробелов, нопосле самого идентификатора должен следовать только символ новой строки. Так, дляопределения идентификатора EXPERIMENTAL служит следующая директива.#define EXPERIMENTAL
ПРИМЕЧАНИЕВ C/C++ директива #define может использоваться для подстановки исходного текста, например для определения имени значения, а также для создания макрокоманд, похожих нафункции. А в C# такое применение директивы #define не поддерживается. В этом языкедиректива #define служит только для определения идентификатора.Директивы #if и #endif
Обе директивы, #if и #endif, допускают условную компиляцию последовательности кода в зависимости от истинного результата вычисления выражения, включающего в себя один или несколько идентификаторов. Идентификатор считается истинным,если он определен, а иначе — ложным. Так, если идентификатор определен директивой #define, то он будет оценен как истинный. Ниже приведена общая форма директивы #if.#if идентификаторное_выражение последовательность операторов#endif
Если идентификаторное_выражение, следующее после директивы #if, истинно,то компилируется код (последовательность операторов), указываемый между ними директивой #endif. В противном случае этот промежуточный код пропускается.Директива #endif обозначает конец блока директивы #if.
Идентификаторное выражение может быть простым, как наименование идентификатора. В то же время в нем разрешается применение следующих операторов: !, ==,!=, && и ||, а также круглых скобок.
Ниже приведен пример применения упомянутых выше директив.// Продемонстрировать применение директив// #if, #endif и #define.#define EXPERIMENTALusing System;class Test { static void Main() { #if EXPERIMENTAL Console.WriteLine("Компилируется для экспериментальной версии."); #endif Console.WriteLine("Присутствует во всех версиях."); }}
Этот код выдает следующий результат.Компилируется для экспериментальной версии.Присутствует во всех версиях.
В приведенном выше коде определяется идентификатор EXPERIMENTAL. Поэтомукогда в этом коде встречается директива #if, идентификаторное выражение вычисляется как истинное и затем компилируется первый оператор, содержащий вызовметода WriteLine(). Если же удалить определение идентификатора EXPERIMENTALи перекомпилировать данный код, то первый оператор, содержащий вызов методаWriteLine(), не будет скомпилирован, поскольку идентификаторное выражение директивы #if вычисляется как ложное. Но второй оператор, содержащий вызов методаWriteLine(), компилируется в любом случае, потому что он не входит в блок директивы #if.
Как пояснялось выше, в директиве #if допускается указывать идентификаторноевыражение. В качестве примера рассмотрим следующую программу.// Использовать идентификаторное выражение.#define EXPERIMENTAL#define TRIALusing System;class Test { static void Main() { #if EXPERIMENTAL Console.WriteLine("Компилируется для экспериментальной версии."); #endif #if EXPERIMENTAL && TRIAL Console.Error.WriteLine ("Проверка пробной экспериментальной версии."); #endif Console.WriteLine("Присутствует во всех версиях."); }}
Эта программа дает следующий результат.Компилируется для экспериментальной версии.Проверка пробной экспериментальной версии.Присутствует во всех версиях.
В данном примере определены два идентификатора: EXPERIMENTAL и TRIAL. Второй оператор, содержащий вызов метода WriteLine(), компилируется лишь в томслучае, если определены оба идентификатора.
Для компилирования кода в том случае, если идентификатор не определен, можновоспользоваться оператором !, как в приведенном ниже примере.#if !EXPERIMENTAL Console.WriteLine("Этот код не экспериментальный!");#endif
Вызов метода будет скомпилирован только в том случае, если идентификаторEXPERIMENTAL не определен.Директивы #else и #elif
Директива #else действует аналогично условному оператору else языка С#, определяя альтернативный ход выполнения программы, если этого не может сделать директива #if. С учетом директивы #else предыдущий пример программы может бытьрасширен следующим образом.// Продемонстрировать применение директивы #else.#define EXPERIMENTALusing System;class Test { static void Main() { #if EXPERIMENTAL Console.WriteLine("Компилируется для экспериментальной версии."); #else Console.WriteLine("Компилируется для окончательной версии."); #endif #if EXPERIMENTAL && TRIAL Console.Error.WriteLine("Проверка пробной экспериментальной версии."); #else Console.Error.WriteLine("Это не пробная экспериментальная версия."); #endif Console.WriteLine("Присутствует во всех версиях."); }}