C# Language
Препроцессорные директивы
Поиск…
Синтаксис
- #define [symbol] // Определяет символ компилятора.
- #undef [symbol] // Undefine символ компилятора.
- #warning [warning message] // Создает предупреждение компилятора. Полезно с #if.
- #error [сообщение об ошибке] // Создает ошибку компилятора. Полезно с #if.
- #line [номер строки] (имя файла) // Переопределяет номер строки компилятора (и, возможно, имя исходного файла). Используется с текстовыми шаблонами T4 .
- #pragma warning [disable | restore] [warning numbers] // Отключает / восстанавливает предупреждения компилятора.
- #pragma checksum " [filename] " " [guid] " " [checksum] " // Проверяет содержимое исходного файла.
- #region [имя региона] // Определяет область складного кода.
- #endregion // Заканчивает блок области кода.
- #if [condition] // Выполняет код ниже, если условие истинно.
- #else // Используется после #if.
- #elif [condition] // Используется после #if.
- #endif // Завершает условный блок, начинающийся с #if.
замечания
Директивы препроцессора обычно используются для облегчения преобразования исходных программ и их легкой компиляции в разных средах исполнения. Директивы в исходном файле сообщают препроцессору выполнять определенные действия. Например, препроцессор может заменить токены в тексте, вставить содержимое других файлов в исходный файл или подавить компиляцию части файла, удалив разделы текста. Линии препроцессора распознаются и выполняются перед расширением макроса. Поэтому, если макрос расширяется во что-то, что выглядит как команда препроцессора, эта команда не распознается препроцессором.
Операторы препроцессора используют тот же набор символов, что и для операторов исходного файла, за исключением того, что escape-последовательности не поддерживаются. Набор символов, используемый в инструкциях препроцессора, совпадает с набором символов выполнения. Препроцессор также распознает отрицательные значения символов.
Условные выражения
Условные выражения ( #if
, #elif
и т. Д.) Поддерживают ограниченное подмножество булевых операторов. Они есть:
-
==
и!=
. Они могут использоваться только для проверки того, является ли символ истинным (определенным) или ложным (не определено) -
&&
,||
,!
-
()
Например:
#if !DEBUG && (SOME_SYMBOL || SOME_OTHER_SYMBOL) && RELEASE == true
Console.WriteLine("OK!");
#endif
будет компилировать код, который печатает "OK!" на консоль, если DEBUG
не определен, определяется SOME_SYMBOL
или SOME_OTHER_SYMBOL
, и определен RELEASE
.
Примечание. Эти замены выполняются во время компиляции и поэтому недоступны для проверки во время выполнения. Код, исключенный с помощью #if
, не является частью выхода компилятора.
См. Также: Директивы препроцессора C # в MSDN.
Условные выражения
Когда компилируется следующее, оно возвращает другое значение в зависимости от того, какие директивы определены.
// Compile with /d:A or /d:B to see the difference
string SomeFunction()
{
#if A
return "A";
#elif B
return "B";
#else
return "C";
#endif
}
Условные выражения обычно используются для регистрации дополнительной информации для отладочных сборников.
void SomeFunc()
{
try
{
SomeRiskyMethod();
}
catch (ArgumentException ex)
{
#if DEBUG
log.Error("SomeFunc", ex);
#endif
HandleException(ex);
}
}
Генерирование предупреждений и ошибок компилятора
Предупреждения компилятора могут быть сгенерированы с #warning
директивы #warning
, а ошибки могут быть сгенерированы с #error
директивы #error
.
#if SOME_SYMBOL
#error This is a compiler Error.
#elif SOME_OTHER_SYMBOL
#warning This is a compiler Warning.
#endif
Определение и определение символов
Символом компилятора является ключевое слово, которое определено во время компиляции, которое можно проверить для условного выполнения определенных разделов кода.
Существует три способа определения символа компилятора. Их можно определить с помощью кода:
#define MYSYMBOL
Они могут быть определены в Visual Studio в разделе «Свойства проекта»> «Создать»> «Условные символы компиляции»:
(Обратите внимание, что DEBUG
и TRACE
имеют свои собственные флажки и не обязательно должны быть указаны явно).
Или они могут быть определены во время компиляции с использованием ключа /define:[name]
на компиляторе C #, csc.exe
.
Вы также можете использовать неопределенные символы, используя директиву #undefine
.
Наиболее распространенным примером этого является символ DEBUG
, который определяется Visual Studio, когда приложение скомпилировано в режиме отладки (в отличие от режима Release).
public void DoBusinessLogic()
{
try
{
AuthenticateUser();
LoadAccount();
ProcessAccount();
FinalizeTransaction();
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Trace.WriteLine("Unhandled exception!");
System.Diagnostics.Trace.WriteLine(ex);
throw;
#else
LoggingFramework.LogError(ex);
DisplayFriendlyErrorMessage();
#endif
}
}
В приведенном выше примере, когда в бизнес-логике приложения возникает ошибка, если приложение скомпилировано в режиме отладки (и установлен символ DEBUG
), ошибка будет записана в журнал трассировки, и исключение будет повторно -отброса для отладки. Однако, если приложение скомпилировано в режиме деблокирования (и не установлен символ DEBUG
), среда регистрации используется для тихого регистрации ошибки, и для конечного пользователя отображается дружественное сообщение об ошибке.
Региональные блоки
Используйте #region
и #endregion
чтобы определить область #endregion
кода.
#region Event Handlers
public void Button_Click(object s, EventArgs e)
{
// ...
}
public void DropDown_SelectedIndexChanged(object s, EventArgs e)
{
// ...
}
#endregion
Эти директивы полезны только тогда, когда для редактирования кода используется среда IDE, которая поддерживает разборчивые области (например, Visual Studio ).
Другие инструкции компилятора
Линия
#line
управляет номером строки и именем файла, сообщенным компилятором при выводе предупреждений и ошибок.
void Test()
{
#line 42 "Answer"
#line filename "SomeFile.cs"
int life; // compiler warning CS0168 in "SomeFile.cs" at Line 42
#line default
// compiler warnings reset to default
}
Контрольная сумма Pragma
#pragma checksum
позволяет специфицировать определенную контрольную сумму для сгенерированной базы данных программ (PDB) для отладки.
#pragma checksum "MyCode.cs" "{00000000-0000-0000-0000-000000000000}" "{0123456789A}"
Использование условного атрибута
Добавление Conditional
атрибута из System.Diagnostics
имен System.Diagnostics
в метод является чистым способом управления тем, какие методы вызывают в ваших сборках, а какие нет.
#define EXAMPLE_A
using System.Diagnostics;
class Program
{
static void Main()
{
ExampleA(); // This method will be called
ExampleB(); // This method will not be called
}
[Conditional("EXAMPLE_A")]
static void ExampleA() {...}
[Conditional("EXAMPLE_B")]
static void ExampleB() {...}
}
Отключение и восстановление предупреждений компилятора
Вы можете отключить предупреждения компилятора с помощью #pragma warning disable
и #pragma warning disable
их с помощью #pragma warning restore
:
#pragma warning disable CS0168
// Will not generate the "unused variable" compiler warning since it was disabled
var x = 5;
#pragma warning restore CS0168
// Will generate a compiler warning since the warning was just restored
var y = 8;
Разрешены номера предупреждений с запятыми:
#pragma warning disable CS0168, CS0219
Префикс CS
является необязательным и может быть даже смешанным (хотя это не лучшая практика):
#pragma warning disable 0168, 0219, CS0414
Пользовательские препроцессоры на уровне проекта
Удобно устанавливать пользовательскую условную предварительную обработку на уровне проекта, когда некоторые действия нужно пропустить, скажем, для тестов.
Перейдите в Solution Explorer
-> Щелкните правой кнопкой мыши по проекту, для которого вы хотите установить переменную, -> Properties
-> Build
-> В поле «Поиск». Conditional compilation symbols
и введите условную переменную здесь.
Пример кода, который пропустит некоторый код:
public void Init()
{
#if !IGNOREREFRESHDB
// will skip code here
db.Initialize();
#endif
}