Директивы C # if /then для debug vs release
-
21-09-2019 - |
Вопрос
В свойствах решения у меня есть конфигурация, установленная на "release" для моего единственного проекта.
В начале основной процедуры у меня есть этот код, и он показывает "Mode=Debug".У меня также есть эти две строки в самом верху:
#define DEBUG
#define RELEASE
Тестирую ли я правильную переменную?
#if (DEBUG)
Console.WriteLine("Mode=Debug");
#elif (RELEASE)
Console.WriteLine("Mode=Release");
#endif
Моя цель - установить разные значения по умолчанию для переменных на основе режима debug vs release.
Решение
Удалите #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, особенно если вы распространяете его по всей своей кодовой базе, поскольку это создаст вам проблемы, когда сборки Debug проходят, но сборки Release завершаются неудачей, если вы не будете осторожны.
Итак, вот что я придумал (вдохновленный #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;
}
}
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='
Метод Debug.Assert
имеет условный атрибут DEBUG
.Если он не определен, вызов и это задание isDebug = true
являются устранен:
Если символ определен, вызов включен;в противном случае вызов (включая оценку параметров вызова) будет пропущен.
Если DEBUG
определяется, isDebug
установлено значение true
(и перешел к Debug.Assert
, который в этом случае ничего не делает).
Если вы пытаетесь использовать переменную , определенную для типа сборки , вам следует удалить эти две строки ...
#define DEBUG
#define RELEASE
...это приведет к #if (ОТЛАДКА) всегда быть правдивым.
Также не существует символа условной компиляции по умолчанию для ОСВОБОЖДЕНИЕ.Если вы хотите определить один из них, перейдите в свойства проекта, нажмите на Строить вкладку, а затем добавить ВЫПУСК в Условные символы компиляции текстовое поле под Общая информация направляюсь.
Другим вариантом было бы сделать это...
#if DEBUG
Console.WriteLine("Debug");
#else
Console.WriteLine("Release");
#endif
Удалите свои определения вверху
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Слегка модифицированный (ублюдочный?) версия ответа Тода Томсона как статическая функция, а не отдельный класс (я хотел иметь возможность вызывать ее в привязке к веб-форме из класса 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
, как таковой:
Поскольку целью этих директив компилятора является указание компилятору НЕ включать код, отладочный код, бета-код или, возможно, код, который необходим всем вашим конечным пользователям, за исключением, скажем, отдела рекламы, т. е.#Определите AdDept, если вы хотите иметь возможность включать или удалять их в зависимости от ваших потребностей.Без необходимости изменять исходный код, если, например, не AdDept сливается с AdDept.Затем все, что нужно сделать, это включить директиву #AdDept на странице свойств параметров компилятора существующей версии программы и выполнить компиляцию и wa la!код объединенной программы оживает!.
Вы также можете захотеть использовать декларативное для нового процесса, который не готов к прайм-тайму или который не может быть активен в коде, пока не придет время его выпустить.
Во всяком случае, именно так я это делаю.
Я начал думать о лучшем способе.До меня дошло, что блоки #if фактически являются комментариями в других конфигурациях (предполагая DEBUG
или RELEASE
;но верно для любого символа)
public class Mytest
{
public DateTime DateAndTimeOfTransaction;
}
public void ProcessCommand(Mytest Command)
{
CheckMyCommandPreconditions(Command);
// do more stuff with Command...
}
[Conditional("DEBUG")]
private static void CheckMyCommandPreconditions(Mytest Command)
{
if (Command.DateAndTimeOfTransaction > DateTime.Now)
throw new InvalidOperationException("DateTime expected to be in the past");
}
Удалите определения и проверьте, находится ли условие в режиме отладки.Вам не нужно проверять, находится ли директива в режиме выпуска.
Что- то вроде этого:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif