Директивы if/then C# для debug vs release
в свойствах решения у меня есть конфигурация, настроенная на "выпуск" для моего одного и единственного проекта.
в начале основной процедуры у меня есть этот код, и он показывает "Mode=Debug". У меня также есть эти две строки в самом верху:
#define DEBUG
#define RELEASE
Я тестирую правильную переменную?
#if (DEBUG)
Console.WriteLine("Mode=Debug");
#elif (RELEASE)
Console.WriteLine("Mode=Release");
#endif
моя цель-установить разные значения по умолчанию для переменных на основе режима отладки и выпуска.
12 ответов
удалить #define DEBUG
в коде. Установите препроцессоры в конфигурации сборки для этой конкретной сборки (DEBUG/_DEBUG должен быть определен в VS уже).
причина, по которой он печатает "Mode=Debug", заключается в вашем #define
а затем пропускает elif
.
кроме того, правильный способ проверить:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Не проверяйте для выпуска
по умолчанию Visual Studio определяет DEBUG, если проект компилируется в режиме отладки и не определяет его, если он находится в режиме выпуска. По умолчанию RELEASE не определяется в режиме Release. Использовать что-то вроде этого:
#if DEBUG
// debug stuff goes here
#else
// release stuff goes here
#endif
если вы хотите сделать что-то только в режиме релиза:
#if !DEBUG
// release...
#endif
также, стоит отметить, что вы можете использовать [Conditional("DEBUG")]
атрибут для методов, которые возвращают void
у них выполняется только при наличии определенных символов. Компилятор удалит все вызовы этих методов, если символ не определен:
[Conditional("DEBUG")]
void PrintLog() {
Console.WriteLine("Debug info");
}
void Test() {
PrintLog();
}
Я предпочитаю проверять его так, как это vs ищет #defines:
if (System.Diagnostics.Debugger.IsAttached)
{
//...
}
else
{
//...
}
С оговоркой, что конечно, вы можете скомпилировать и развернуть что-то в режиме отладки, но еще не подключен отладчик.
Я не большой поклонник материала #if, особенно если вы распространяете его вокруг своей базы кода, поскольку это даст вам проблемы, когда отладочные сборки проходят, но выпускные сборки терпят неудачу, если вы не осторожны.
Итак, вот что я придумал (вдохновленный #ifdef в C#):
public interface IDebuggingService
{
bool RunningInDebugMode();
}
public class DebuggingService : IDebuggingService
{
private bool debugging;
public bool RunningInDebugMode()
{
//#if DEBUG
//return true;
//#else
//return false;
//#endif
WellAreWe();
return debugging;
}
[Conditional("DEBUG")]
private void WellAreWe()
{
debugging = true;
}
}
Если вы пытаетесь использовать переменную, определенную для типа сборки, вы должны удалить две строки ...
#define DEBUG
#define RELEASE
... это вызовет #if (DEBUG) всегда быть правдой.
также нет условного символа компиляции по умолчанию для релиз. Если вы хотите определить один перейти к свойствам проекта, нажмите на построить вкладка, а затем добавить релиз в условная компиляция символов текстовое поле под общие заголовок.
другой вариант-сделать это...
#if DEBUG
Console.WriteLine("Debug");
#else
Console.WriteLine("Release");
#endif
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='
метод Debug.Assert
имеет условный атрибут DEBUG
. Если он не определен, вызов и назначении isDebug = true
are ликвидировано:
если символ определен, вызов включен; в противном случае вызов (включая оценку параметров вызова) опущен.
если DEBUG
определяется isDebug
установлено значение true
(и перешло к Debug.Assert
, который ничего не делает в это дело.)
удалите свои определения в верхней части
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
немного изменен (извращенные?) версия ответа Тода Томсона как статическая функция, а не отдельный класс (я хотел иметь возможность вызывать его в viewbinding WebForm из класса viewutils, который я уже включил).
public static bool isDebugging() {
bool debugging = false;
WellAreWe(ref debugging);
return debugging;
}
[Conditional("DEBUG")]
private static void WellAreWe(ref bool debugging)
{
debugging = true;
}
пространство имен
using System.Resources;
using System.Diagnostics;
метод
private static bool IsDebug()
{
object[] customAttributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
if ((customAttributes != null) && (customAttributes.Length == 1))
{
DebuggableAttribute attribute = customAttributes[0] as DebuggableAttribute;
return (attribute.IsJITOptimizerDisabled && attribute.IsJITTrackingEnabled);
}
return false;
}
совет, который может спасти вас много времени - не забывайте, что даже если вы выберете debug
в конфигурации сборки (в меню vs2012 / 13 В разделе BUILD => CONFIGURATION MANAGER) - этого недостаточно.
вы должны обратить внимание на публикацию Configuration
, например:
поскольку цель этих директив компилятора состоит в том, чтобы сказать компилятору не включать код,отладочный код, бета-код или, возможно, код, который необходим всем вашим конечным пользователям, за исключением, скажем, рекламного отдела, т. е. #Define AdDept вы хотите иметь возможность включать или удалять их в зависимости от ваших потребностей. Без необходимости изменять исходный код, если, например, не AdDept сливается с AdDept. Тогда все, что нужно сделать, это включить директиву #AdDept в параметры компилятора страница свойств существующей версии программы и сделать компиляцию и wa la! код Объединенной программы оживает!.
вы также можете использовать декларатив для нового процесса, который не готов к прайм-тайму или который не может быть активен в коде, пока не придет время его выпустить.
во всяком случае, так я это делаю.
обязательно определите константу отладки в свойствах сборки проекта. Это позволит #if DEBUG
. Я не вижу предопределенной константы выпуска, поэтому это может означать, что все, что не находится в блоке отладки, является режимом выпуска.