C # if / then directives pour le débogage vs libération
-
21-09-2019 - |
Question
Dans les propriétés Solution, je Configuration réglé sur « libération » pour mon seul et unique projet.
Au début de la routine principale, je le code, et il affiche « Mode = Debug ». J'ai aussi ces deux lignes au sommet:
#define DEBUG
#define RELEASE
Suis-je tester la variable à droite?
#if (DEBUG)
Console.WriteLine("Mode=Debug");
#elif (RELEASE)
Console.WriteLine("Mode=Release");
#endif
Mon but est de définir différents paramètres par défaut pour les variables en fonction de débogage vs mode de libération.
La solution
Supprimer le #define DEBUG
dans votre code. Set préprocesseur dans la configuration de construction pour cette version spécifique (debug / _DEBUG doit être défini dans VS déjà).
La raison pour laquelle il imprime "Mode = Debug" est à cause de votre #define
puis saute le elif
.
En outre, la bonne façon de vérifier est:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Ne pas vérifier RELEASE
Autres conseils
Par défaut, Visual Studio définit DEBUG si le projet est compilé en mode débogage et ne définit pas si elle est en mode de sortie. RELEASE n'est pas défini en mode de sortie 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 que dans le mode de sortie:
#if !DEBUG
// release...
#endif
En outre, il est intéressant de souligner que vous pouvez utiliser l'attribut [Conditional("DEBUG")]
sur les méthodes qui retournent void
pour qu'ils n'exécutés si un certain symbole est défini. Le compilateur supprimerait tous les appels à ces méthodes si le symbole est pas défini:
[Conditional("DEBUG")]
void PrintLog() {
Console.WriteLine("Debug info");
}
void Test() {
PrintLog();
}
Je préfère vérifier comme ça vs recherche #defines:
if (System.Diagnostics.Debugger.IsAttached)
{
//...
}
else
{
//...
}
Avec la mise en garde bien sûr, vous pouvez compiler et déployer quelque chose en mode débogage, mais toujours pas le débogueur attaché.
Je ne suis pas un grand fan des trucs #if, surtout si vous étalez tout autour de votre base de code comme il vous donnera des problèmes où debug passe mais échoue si versions Release 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 DEBUG
attribut conditionnel. Si ce n'est pas défini, l'appel et l'affectation sont isDebug = true
éliminé :
Si le symbole est défini, l'appel est inclus; Sinon, l'appel (y compris l'évaluation des paramètres de l'appel) est omise.
Si DEBUG
est défini, isDebug
est réglé sur true
(et passé à Debug.Assert
, 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
... ce ramènerai les #if (debug) pour être toujours vrai.
En outre il n'y a pas un symbole par défaut de compilation conditionnelle pour RELEASE . Si vous souhaitez définir un aller aux propriétés du projet, cliquez sur le bouton Construire onglet puis ajouter RELEASE symboles de compilation conditionnelle zone de texte sous la Général cap.
L'autre option serait de le faire ...
#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
modifié légèrement (bâtarde?) Version de la réponse par Tod Thomson en fonction statique plutôt que d'une catégorie distincte (je voulais pouvoir l'appeler dans un WebForm viewbinding d'une classe viewutils j'avais déjà inclus).
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;
}
Une astuce qui peut vous faire économiser beaucoup de temps - ne pas oublier que même si vous choisissez debug
sous la configuration de construction (le menu vs2012 / 13, il est sous BUILD => GESTIONNAIRE DE CONFIGURATION) - cela ne suffit pas.
Vous devez prêter attention à la PUBLIER Configuration
, en tant que tel:
Étant donné que le but de ces directives de compilation doivent dire au compilateur de ne pas inclure le code, le code de débogage, le code bêta, ou un code peut-être qui est nécessaire par tous vos utilisateurs finaux, sauf dire ceux du département de la publicité, à savoir #Define AdDept vous voulez être en mesure d'inclure ou les supprimer en fonction de vos besoins. Sans avoir à changer votre code source si par exemple un non AdDept se fond dans le AdDept. Ensuite, tout ce qui doit être fait est d'inclure la directive #AdDept dans les propriétés des options compilateur page une version existante du programme et faire une compilation et wa la! le code du programme fusionné jaillit en vie!.
Vous pouvez également utiliser un déclarative pour un nouveau processus qui n'est pas prêt pour le prime time ou qui ne peuvent pas être actifs dans le code jusqu'à ce qu'il est temps de le libérer.
Quoi qu'il en soit, c'est la façon dont je le fais.
Je suis arrivé à penser à une meilleure façon. Il me vint à l'esprit que les blocs de #if des commentaires efficacement dans d'autres configurations (en supposant DEBUG
ou RELEASE
, mais vrai avec un 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");
}
Supprimer les définitions et vérifier 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 ceci:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif