2010-01-20 11 views
316

Nelle proprietà della soluzione, ho configurato la configurazione su "release" per il mio unico progetto.C# if/then direttive per debug vs release

All'inizio della routine principale, ho questo codice, e mostra "Modalità = Debug". Ho anche queste due righe al vertice:

#define DEBUG 
#define RELEASE 

Am I test la variabile giusto?

#if (DEBUG) 
      Console.WriteLine("Mode=Debug"); 
#elif (RELEASE) 
      Console.WriteLine("Mode=Release"); 
#endif 

Il mio obiettivo è impostare valori predefiniti diversi per le variabili in base alla modalità di debug vs release.

+10

si sta definendo SIA debug e rilascio. –

risposta

544

Rimuovere il #define DEBUG nel codice. Impostare i preprocessori nella configurazione di build per quella build specifica (DEBUG/_DEBUG dovrebbe essere già definito in VS).

La ragione per cui stampa "Modalità = Debug" è a causa del tuo #define e quindi salta lo elif.

Inoltre, il modo giusto per controllare è:

#if DEBUG 
    Console.WriteLine("Mode=Debug"); 
#else 
    Console.WriteLine("Mode=Release"); 
#endif 

Non controllare la STAMPA

+56

Volevo aggiungere che se si volesse controllare solo per RELEASE, si può fare questo: #if! DEBUG –

+3

Perché '# if' e non' # ifdef'? –

+20

@ BobStein-VisiBone Ricordate che stiamo parlando di C# qui, non di C. '# ifdef' è specifico per il preprocessore di C/C++, C# richiede l'uso di' # if'. – jduncanator

17

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 esiste un simbolo di compilazione condizionale predefinito per RELEASE. Se si desidera definire una proprietà di progetto, fare clic sulla scheda Build e quindi aggiungere RELEASE ai simboli di compilazione nella sezione General.

L'altra opzione sarebbe quella di fare questo ...

#if DEBUG 
    Console.WriteLine("Debug"); 
#else 
    Console.WriteLine("Release"); 
#endif 
230

Per impostazione predefinita, Visual Studio definisce DEBUG se il progetto viene compilato in modalità debug e non definisce se è in modalità di rilascio. RELEASE non è definito in modalità Release 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 per farli eseguito solo se viene definito un determinato simbolo. 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(); 
} 
+3

Risposta stupenda, apprezzata. –

7

Rimuovere i tuoi definisce in cima

#if DEBUG 
     Console.WriteLine("Mode=Debug"); 
#else 
     Console.WriteLine("Mode=Release"); 
#endif 
147

preferisco controllando in questo modo vs cercando #defines:

if (System.Diagnostics.Debugger.IsAttached) 
{ 
    //... 
} 
else 
{ 
    //... 
} 

Con l'avvertimento che ovviamente è possibile compilare e distribuire qualcosa in modalità di debug ma non avere ancora il debugger collegato.

+1

Grazie! Non so ancora cosa siano "#defines", quindi questa è un'ottima soluzione! – Tim

+1

Questa è una bella soluzione, grazie! – yenta

+0

E nel mio caso, questo fa esattamente quello che voglio. In realtà voglio sapere se ho un debugger collegato, perché so di avere un codice che non voglio eseguire se ho un debugger collegato. Questo e spettacolare! – JFTxJ

4

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; 
    } 
43

Io non sono un grande fan della roba #if, soprattutto se si spalmano tutto intorno al vostro codice di base in quanto vi darà problemi in cui Le build di debug passano ma i build di Release falliscono se non stai attento.

Così qui è quello che sono venuto su con (ispirato #ifdef 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; 
    } 
} 
+2

Ehi, è molto creativo. Mi piace il tuo uso dell'attributo per impostare la proprietà. – kenchilada

+3

Questo ha il vantaggio di non essere colpito da refactoring bug in Resharper che può rovinare il codice in base alla configurazione condizionale corrente. – Jafin

+1

Mi piace questo, ma mi chiedo perché non creare un'implementazione singleton per questo invece di un servizio. È specifico per il sistema e ti impedisce di doverlo iniettare ovunque. (puoi immaginare uno scenario in cui l'implementazione di questa funzionalità sarebbe diversa? – BastanteCaro

0

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 codice necessario per tutti gli utenti finali, ad eccezione di quelli del dipartimento pubblicitario, ovvero #Define AdDept che si desidera includere o rimuovere in base alle proprie esigenze. Senza dover modificare il codice sorgente se ad esempio un non AdDept si fonde con AdDept. Quindi tutto ciò che deve essere fatto è includere la direttiva #AdDept nella pagina delle proprietà delle opzioni del compilatore di una versione esistente del programma e fare una compilazione e wa la! il codice del programma unito nasce vivo !.

Si potrebbe anche voler utilizzare un dichiarativo per un nuovo processo che non è pronto per il prime time o che non può essere attivo nel codice finché non è il momento di rilasciarlo.

In ogni caso, questo è il modo in cui lo faccio.

11
bool isDebug = false; 
Debug.Assert(isDebug = true); // '=', not '==' 

Procedimento Debug.Assert ha attributo condizionale DEBUG. Se non è definito, la chiamata e l'assegnazioneisDebug = true sono eliminated:

Se il simbolo è definito, la chiamata è incluso; in caso contrario, la chiamata (inclusa la valutazione dei parametri della chiamata) viene omessa.

Se DEBUG è definito, isDebug è impostato true (e passato a Debug.Assert, che non fa nulla in questo caso).

+0

Questa è anche una soluzione piuttosto creativa. :) – Jack

5

Versione leggermente modificata (bastarda?) Della risposta di Tod Thomson come funzione statica piuttosto che una classe separata (volevo essere in grado di chiamarla in una vista WebForm da una classe viewutils che 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; 
} 
2

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 PUBBLICARE Configuration, come ad esempio:

enter image description here

Problemi correlati