C#, если/затем директивы для отладки против освобождения
в свойствах решения у меня есть конфигурация, установленная на "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, если проект компилируется в режиме отладки, и не определяет его, если он находится в режиме выпуска. Выпуск не определен в режиме выпуска по умолчанию. Использовать что-то вроде этого:
#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(); }
Я предпочитаю проверять его так, а не искать #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
слегка модифицированный (ублюдок?) версия ответа Tod Thomson как статическая функция, а не отдельный класс (я хотел иметь возможность вызывать его в веб-форме viewbinding из класса 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! код Объединенной программы оживает!.
вы также можете использовать декларатив для нового процесса, который не готов к прайм-тайм или который не может быть активен в коде, пока не придет время его освободить.
во всяком случае, так я это делаю.