Dans les propriétés de la solution, la configuration est configurée sur "release" pour mon seul et unique projet.
Au début de la routine principale, j'ai ce code qui affiche "Mode = Debug". J'ai aussi ces deux lignes tout en haut:
#define DEBUG
#define RELEASE
Est-ce que je teste la bonne variable?
#if (DEBUG)
Console.WriteLine("Mode=Debug");
#Elif (RELEASE)
Console.WriteLine("Mode=Release");
#endif
Mon objectif est de définir différentes valeurs par défaut pour les variables en fonction du mode débogage vs version.
Supprimez le #define DEBUG
de votre code. Définissez les préprocesseurs dans la configuration de construction pour cette construction spécifique (DEBUG/_DEBUG doit déjà être défini dans le VS).
La raison pour laquelle il imprime "Mode = Debug" est à cause de votre #define
puis ignore la Elif
.
Aussi, la bonne façon de vérifier est:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Ne pas vérifier pour la libération
Par défaut, Visual Studio définit DEBUG si le projet est compilé en mode débogage et ne le définit pas s'il est en mode publication. RELEASE n'est pas défini en mode Release par défaut. Utilisez quelque chose comme ceci:
#if DEBUG
// debug stuff goes here
#else
// release stuff goes here
#endif
Si vous voulez faire quelque chose uniquement en mode release:
#if !DEBUG
// release...
#endif
Il est également intéressant de noter que vous pouvez utiliser l'attribut [Conditional("DEBUG")]
sur les méthodes qui renvoient void
pour les exécuter uniquement si un certain symbole est défini. Le compilateur supprimerait tous les appels à ces méthodes si le symbole n'est pas défini:
[Conditional("DEBUG")]
void PrintLog() {
Console.WriteLine("Debug info");
}
void Test() {
PrintLog();
}
Je préfère vérifier comme ceci contre la recherche de #defines:
if (System.Diagnostics.Debugger.IsAttached)
{
//...
}
else
{
//...
}
Avec l'avertissement que vous pouvez bien sûr compiler et déployer quelque chose en mode débogage sans toujours avoir le débogueur attaché.
Je ne suis pas un grand fan des choses #if, en particulier si vous le répartissez tout autour de votre base de code car cela vous posera des problèmes lorsque les générations Debug passent mais que les versions Release échouent si vous ne faites pas attention.
Alors voici ce que je suis venu avec (inspiré par # ifdef en 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 '=='
_
La méthode Debug.Assert
a l'attribut conditionnel DEBUG
. S'il n'est pas défini, l'appel et l'affectation _isDebug = true
_ sont éliminés :
Si le symbole est défini, l'appel est inclus. sinon, l'appel (y compris l'évaluation des paramètres de l'appel) est omis.
Si DEBUG
est défini, isDebug
est défini sur true
(et transmis à _Debug.Assert
_, ce qui ne fait rien dans ce cas).
Si vous essayez d'utiliser la variable définie pour le type de construction, vous devez supprimer les deux lignes ...
#define DEBUG
#define RELEASE
... ceci fera que # if (DEBUG) sera toujours vrai.
Il n’existe pas non plus de symbole de compilation conditionnelle par défaut pour RELEASE. Si vous voulez en définir un, allez dans les propriétés du projet, cliquez sur l'onglet Build, puis ajoutez RELEASE à la zone de texte Symboles de compilation conditionnelle sous Général rubrique.
L'autre option serait de faire cela ...
#if DEBUG
Console.WriteLine("Debug");
#else
Console.WriteLine("Release");
#endif
Supprimer vos définit en haut
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Version légèrement modifiée (bastardisée?) De la réponse par Tod Thomson sous forme de fonction statique plutôt que de classe séparée (je voulais pouvoir l'appeler dans une liaison de vue WebForm à partir d'une classe de viewutils que j'avais déjà incluse).
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;
Méthode
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 conseil qui peut vous faire gagner beaucoup de temps - n’oubliez pas que même si vous choisissez debug
dans la configuration de construction (dans le menu vs2012/13, c’est sous BUILD => CONFIGURATION MANAGER) - c’est insuffisant.
Vous devez faire attention à PUBLISH Configuration
, en tant que tel:
J'ai commencé à penser à un meilleur moyen. Il m'est apparu que #si les blocs sont effectivement des commentaires dans d'autres configurations (en supposant que DEBUG
ou RELEASE
; mais vrai avec n'importe quel symbole)
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");
}
Dans la mesure où ces directives COMPILER ont pour but d'indiquer au compilateur de ne PAS inclure de code, de code de débogage, de code bêta ou peut-être de code nécessaire à tous vos utilisateurs finaux, à l'exception du service publicité, par exemple #Define AdDept que vous souhaitez. pouvoir les inclure ou les supprimer en fonction de vos besoins. Sans avoir à changer votre code source si, par exemple, un non-AdDept est fusionné dans AdDept. Ensuite, tout ce qui reste à faire est d’inclure la directive #AdDept dans la page de propriétés des options du compilateur d’une version existante du programme et de compiler et wa la! le code du programme fusionné prend vie!.
Vous pouvez également utiliser un déclaratif pour un nouveau processus qui n'est pas prêt pour le prime time ou qui ne peut pas être actif dans le code tant qu'il n'est pas temps de le publier.
Quoi qu'il en soit, c'est comme ça que je le fais.
Supprimez les définitions et vérifiez si le conditionnel est en mode débogage. Vous n'avez pas besoin de vérifier si la directive est en mode de libération.
Quelque chose comme ça:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif