Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

2.5.3Директивы объявлений

Директивы объявлений используются для определения или отмены определения символов условной компиляции.

ПРО_описание: пробелнеоб # пробелнеоб define пробел условный_символ ПРО_новая_строка пробелнеоб # пробелнеоб undef пробел условный_символ ПРО_новая_строка

ПП_новая_строка: пробелнеобязательно однострочный_комментарийнеобязательно следующая_строка

Обработка директивы #define делает данный символ условной компиляции определенным, начиная с исходной строки, следующей за директивой. Подобным же образом обработка директивы #undef делает данный символ условной компиляции неопределенным, начиная с исходной строки, следующей за директивой.

Все директивы #define и #undef в исходном файле должны стоять до первой лексемы (§2.4) в исходном файле, иначе вызывается ошибка времени компиляции. Интуитивно понятно, что директивы #define и #undef должны предшествовать любому «фактическому коду» в исходном файле.

В примере

#define Enterprise

#if Professional || Enterprise #define Advanced #endif

namespace Megacorp.Data { #if Advanced class PivotTable {...} #endif }

правильно, так как директивы #define предшествуют первой лексеме (ключевое слово namespace) в исходном файле.

Следующий пример приводит к ошибке времени компиляции, так как директива #define следует за фактическим кодом:

#define A namespace N { #define B #if B class Class1 {} #endif }

Директива #define может определять уже определенный символ условной компиляции, без какого-либо вмешательства директивы #undef для этого символа. В следующем примере символ условной компиляции A определен, а затем определен снова.

#define A #define A

Директива #undef может «отменить определение» не определенного символа условной компиляции. В следующем примере определен символ условной компиляции A, а затем дважды отменено его определение; хотя вторая директива #undef не действует, она все же допустима.

#define A #undef A #undef A

2.5.4Директивы условной компиляции

Директивы условной компиляции используются для условного включения или исключения частей исходного файла.

ПП_условное_выражение: ПП_раздел_if ПП_разделы_elifнеобязательно ПП_раздел_elseнеобязательно ПП_endif

ПП_раздел_if: пробелнеобязательно # пробелнеобязательно if пробел ПП_выражение ПП_новая_строка раздел_условного_выражениянеобязательно

ПП_разделы_elif: ПП_раздел_elif ПП_разделы_elif ПП_раздел_elif

ПП_раздел_elif: пробелнеобязательно # пробелнеобязательно elif пробел ПП_выражение ПП_новая_строка раздел_условного_выражениянеобязательно

ПП_раздел_else: пробелнеобязательно # пробелнеобязательно else ПП_новая_строка раздел_условного_выражениянеобязательно

ПП_endif: пробелнеобязательно # пробелнеобязательно endif ПП_новая_строка

раздел_условного_выражения: раздел_ввода пропущенный_раздел

пропущенные_символы: часть_пропущенных_символов пропущенный символ часть_пропущенных_символов

часть_пропущенных_символов: пропущенные_символынеобязательно новая_строка ПП_директива

пропущенные_символы: пробелнеобязательно не_знак_числа входные_символынеобязательно

не_знак_числа: любой входной_символ, кроме #

В соответствии с синтаксисом, директивы условной компиляции должны быть записаны как наборы, состоящие из (по порядку) директивы #if, нуля или более директив #elif, нуля или одной директивы #else и директивы #endif. Между этими директивами находятся условные разделы исходного кода. Каждый раздел управляется непосредственно предшествующей директивой. Условный раздел может содержать вложенные директивы условной компиляции при условии, что они образуют полные наборы.

ПП_условное_выражение выделяет не более одного из содержащихся условных_разделов для обычной лексической обработки:

  • ПП_выражения директив #if и #elif вычисляются по порядку, пока одна из них не выдаст значение true. Если выражение выдает true, выбирается условный_раздел соответствующей директивы;

  • если все ПРО_выражения дают false и если имеется директива #else, выбирается условный_раздел директивы #else;

  • иначе условный_раздел не выбирается.

Выбранный условный_раздел, если он есть, обрабатывается как обычный раздел_ввода: в исходном коде, содержащемся в этом разделе, должна соблюдаться лексическая грамматика; лексемы создаются из исходного кода в разделе, а препроцессорные директивы в разделе имеют предписанные действия.

Оставшиеся условные_разделы, если они есть, обрабатываются как пропущенные_разделы: за исключением препроцессорных директив, исходный код в разделе не обязан соблюдать лексическую грамматику; в этом разделе не создаются лексемы из исходного кода, а препроцессорные директивы должны быть лексически правильными, но в других отношениях они не обрабатываются. Внутри условного_раздела, который обрабатывается как пропущенный_раздел, любые вложенные условные_разделы (содержащиеся во вложенных конструкциях #if...#endif и #region...#endregion) также обрабатываются как пропущенные_разделы.

В следующем примере показано, как могут вкладываться директивы условной компиляции:

#define Debug // Debugging on #undef Trace // Tracing off

class PurchaseTransaction { void Commit() { #if Debug CheckConsistency(); #if Trace WriteToLog(this.ToString()); #endif #endif CommitHelper(); } }

За исключением препроцессорных директив, пропущенный исходный код не является предметом лексического анализа. Например, следующее допустимо, несмотря на незавершенный комментарий в разделе #else:

#define Debug // Debugging on

class PurchaseTransaction { void Commit() { #if Debug CheckConsistency(); #else /* Do something else #endif } }

При этом следует учитывать, что препроцессорные директивы должны быть лексически правильными даже в пропущенных разделах исходного кода.

Препроцессорные директивы не обрабатываются, если они находятся внутри элементов ввода в несколько строк. Например, программа

class Hello { static void Main() { System.Console.WriteLine(@"hello, #if Debug world #else Nebraska #endif "); } }

имеет результатом:

hello, #if Debug world #else Nebraska #endif

В особенных случаях обрабатываемый набор препроцессорных директив может зависеть от вычисления ПРО_выражения. В примере

#if X /* #else /* */ class Q { } #endif

в любом случае создается тот же самый поток лексем (class Q { }), независимо от того, определен X или нет. Если X определен, из-за многострочного комментария обрабатываются только директивы #if и #endif. Если X не определен, то три директивы (#if, #else и #endif) являются частью набора директив.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]