Как использовать директивы #if в C # (3.0) - PullRequest
0 голосов
/ 21 апреля 2010

Я только что нашел два куска кода

#if CONSOLE // defined by the console version using 
ournamespace.FactoryInitializer;
#endif

и

#if _NET_1_1
                    log4net.Config.DOMConfigurator.ConfigureAndWatch(new System.IO.FileInfo(s) );
#else
                    log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(s) );
#endif

Может ли кто-нибудь подсказать мне с работающим примером (пожалуйста, предоставьте простой), каково значение этих фрагментов кода и когда и как их использовать?

Спасибо.

Ответы [ 4 ]

11 голосов
/ 21 апреля 2010

Конечно. Они относятся к условным символам компиляции , которые могут быть определены во время компиляции и которые управляют тем, какой код фактически создается. Вот пример:

using System;

class Test
{
    static void Main()
    {
#if FOO
        Console.WriteLine("FOO was defined");
#endif        

#if BAR
        Console.WriteLine("BAR was defined");
#endif                
    }
}

Если вы скомпилируете это с

csc Test.cs

Это ничего не напечатает. Если вы скомпилируете это с

csc Test.cs /D:FOO

тогда будет напечатано "FOO был определен" - и, очевидно, то же самое верно для BAR.

Обратите внимание, что это не то же самое, что макросы C ++ - символ либо определен, либо нет; оно не имеет «заменяющей стоимости» как таковой.

В Visual Studio вы указываете, какие символы должны быть определены на вкладке «Построение» свойств проекта. Кроме того, в самом начале файла вы можете явно определить и отменить определение символов:

#define FOO
#undef BAR

Это может быть важно при вызове методов, оформленных ConditionalAttribute - такие вызовы игнорируются компилятором, если соответствующий символ не определен. Поэтому, если вы хотите убедиться, что все ваши Debug.Print звонки были выполнены, даже если вы не определили символ DEBUG для остальной части проекта, вы можете использовать:

#define DEBUG
...
Debug.Print("Foo");

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

РЕДАКТИРОВАТЬ: Просто для пояснения терминологии - #if, #line, #pragma и т. Д. Являются директивами препроцессора; FOO и BAR (в данном случае) - условные символы компиляции.

2 голосов
/ 21 апреля 2010

Они используются для условной компиляции .

Если CONSOLE (известный как символ условной компиляции) определен для первого примера с #define CONSOLE, код внутри #if CONSOLE и #endif будет скомпилирован и встроен в сборку, иначе компилятор игнорирует код внутри них ,

Отмена условного символа компиляции осуществляется через #undef, например, #undef CONSOLE. Спецификация языка также гласит:

Нет требования условная компиляция символов будет явно объявлено, прежде чем они упоминается в предварительной обработке выражения. Вместо этого, необъявленный символы просто не определены и, таким образом, имеют значение false.

1 голос
/ 21 апреля 2010

Они называются директивами препроцессора .Цитата из документов:

'# if' позволяет вам начать условную директиву, проверяя символ или символы, чтобы увидеть, имеют ли они значение true.Если они верны в true, компилятор оценивает весь код между #if и следующей директивой.

Так что, в основном, когда вы компилируете свою программу с ключом / define: symbol он будет либо оценивать оператор if, либо нет.Например:

csc foo.cs /define:DEBUG 

позволяет определить директиву DEBUG и ввести ветку #if DEBUG.Помните, что в отличие от оператора if это просто время компиляции, и тело оператора else даже не будет включено в вашу скомпилированную сборку.

0 голосов
/ 21 апреля 2010

Ваш проект может иметь несколько конфигураций, наиболее распространенными являются Debug и Release. В режиме отладки вы можете выводить строки отладки, выполнять дополнительную проверку и т. Д.

Например:

void a(int x){    
    #if DEBUG
    System.Diagnostics.Debug.WriteLine("a("+x+")");
    #endif
    //Do stuff.
}

Вы можете определять директивы для всего проекта в свойствах проекта и создавать сборки отладки / выпуска, или вы можете создать приложение, которое использует разные библиотеки для некоторого вывода (OpenGL / XNA). Или, как у вас, #if _NET_1_1 проверяет, определен ли символ _NET_1_1, предполагая, что .NET FX 1.1 используется и использует надлежащие классы, чтобы вы могли ориентироваться на несколько версий каркаса в нескольких конфигурациях проекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...