Поиск…


Синтаксис

  • #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 в разделе «Свойства проекта»> «Создать»> «Условные символы компиляции»:

Символы компилятора VS

(Обратите внимание, что 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
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow