C # if / then direttive per il debug vs rilascio
-
21-09-2019 - |
Domanda
In proprietà della soluzione, devo configurazione impostata su "release" per il mio unico e solo progetto.
All'inizio della routine principale, ho questo codice, e sta mostrando "Mode = Debug". Ho anche queste due righe al vertice:
#define DEBUG
#define RELEASE
Sto testando la variabile giusto?
#if (DEBUG)
Console.WriteLine("Mode=Debug");
#elif (RELEASE)
Console.WriteLine("Mode=Release");
#endif
Il mio obiettivo è quello di impostare diversi valori di default per le variabili basate su di debug vs modalità di rilascio.
Soluzione
Rimuovere la #define DEBUG
nel codice. Impostare preprocessori nella configurazione di generazione per quella specifica costruzione (DEBUG / _DEBUG dovrebbe essere definito in VS già).
La ragione per la stampa "Mode = Debug" è a causa della vostra #define
e poi salta il elif
.
Inoltre, il modo giusto per controllare è:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Non controllare la STAMPA
Altri suggerimenti
Per impostazione predefinita, Visual Studio definisce DEBUG se il progetto viene compilato in modalità debug e non definisce se è in modalità di rilascio. STAMPA non è definito in modalità di rilascio per impostazione predefinita. Usa qualcosa come questo:
#if DEBUG
// debug stuff goes here
#else
// release stuff goes here
#endif
Se si vuole fare qualcosa solo in modalità di rilascio:
#if !DEBUG
// release...
#endif
Inoltre, vale la pena sottolineare che è possibile utilizzare l'attributo [Conditional("DEBUG")]
sui metodi che restituiscono void
averli eseguiti solo se un certo simbolo è definito. Il compilatore eliminerebbe tutte le chiamate a questi metodi se il simbolo non è definito:
[Conditional("DEBUG")]
void PrintLog() {
Console.WriteLine("Debug info");
}
void Test() {
PrintLog();
}
Io preferisco controllando in questo modo contro alla ricerca di #defines:
if (System.Diagnostics.Debugger.IsAttached)
{
//...
}
else
{
//...
}
Con l'avvertenza che, naturalmente, si può compilare e distribuire qualcosa in modalità debug, ma ancora non hanno il debugger collegato.
Io non sono un grande fan della roba #if, soprattutto se si spalmano tutto intorno la vostra base di codice come vi darà problemi in cui Debug costruisce passaggio ma la liberatoria costruisce esito negativo se non stai attento.
Quindi, ecco cosa sono venuto su con (ispirato da in 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 '=='
Il metodo Debug.Assert
ha condizionale attributo DEBUG
. Se non è definito, la chiamata e l'assegnazione isDebug = true
sono eliminato :
Se il simbolo è definito, la chiamata è incluso; altrimenti, la chiamata (compresa la valutazione dei parametri della chiamata) viene omesso.
Se DEBUG
è definito, isDebug
è impostato su true
(e passato al Debug.Assert
, che non fa nulla in questo caso).
Se si sta tentando di utilizzare la variabile definita per il tipo di costruzione è necessario rimuovere le due linee ...
#define DEBUG
#define RELEASE
... questi farà sì che il #if (DEBUG) per essere sempre vero.
Inoltre, non c'è un simbolo di compilazione condizionale di default per RELEASE . Se si vuole definire uno andare alle proprietà del progetto, fare clic sul scheda Crea e quindi aggiungere disperdere simboli di compilazione condizionale casella di testo sotto il Generale intestazione.
L'altra opzione sarebbe quella di fare questo ...
#if DEBUG
Console.WriteLine("Debug");
#else
Console.WriteLine("Release");
#endif
Rimuovi i tuoi definisce in alto
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Un po 'modificato (imbastardito?) Versione della risposta da Tod Thomson come funzione statica piuttosto che una classe separata (volevo essere in grado di chiamare in un WebForm viewbinding da una classe viewutils avevo già incluso).
public static bool isDebugging() {
bool debugging = false;
WellAreWe(ref debugging);
return debugging;
}
[Conditional("DEBUG")]
private static void WellAreWe(ref bool debugging)
{
debugging = true;
}
NameSpace
using System.Resources;
using System.Diagnostics;
Metodo
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;
}
Un consiglio che può risparmiare un sacco di tempo - non dimenticate che anche se si sceglie debug
sotto la configurazione di generazione (su vs2012 13 Menu / è sotto BUILD => Configuration Manager) - questo non basta.
È necessario prestare attenzione al Configuration
PUBBLICARE, come ad esempio:
Dato che lo scopo di queste direttive del compilatore sono per dire al compilatore di non includere il codice, il codice di debug, il codice beta, o forse il codice che è necessario per tutti gli utenti finali, ad eccezione di quelli dire reparto pubblicità, vale a dire #Define AdDept si vuole essere in grado includere o rimuoverli in base alle vostre esigenze. Senza dover modificare il codice sorgente, se ad esempio un non AdDept si fonde nel AdDept. Quindi tutto ciò che deve essere fatto è quello di includere la direttiva #AdDept nel compilatore pagina Opzioni proprietà di una versione esistente del programma e fare una compilazione e wa la! codice del programma fusione scaturisce vivo!.
Si potrebbe anche voler utilizzare una dichiarativa per un nuovo processo che non è pronto per la prima serata o che non possono essere attivi nel codice fino a quando è il momento di rilasciarlo.
In ogni caso, questo è il modo in cui lo faccio.
ho avuto modo di pensare a un modo migliore. Mi resi conto che i blocchi #if sono commenti efficacemente in altre configurazioni (assumendo DEBUG
o RELEASE
, ma vero con qualsiasi simbolo)
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");
}
Rimuovi le definizioni e verificare se il condizionale è in modalità di debug. Non è necessario verificare se la direttiva è in modalità di rilascio.
Qualcosa di simile a questo:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif