Code "Nur debuggen", der nur ausgeführt werden soll, wenn "aktiviert"

91

Ich möchte einen C # -Code "nur debuggen" hinzufügen, der nur ausgeführt wird, wenn die debuggende Person dies anfordert. In C ++ habe ich etwas Ähnliches gemacht:

void foo()
{   
  // ...
  #ifdef DEBUG
  static bool s_bDoDebugOnlyCode = false;
  if (s_bDoDebugOnlyCode)
  {
      // Debug only code here gets executed when the person debugging 
      // manually sets the bool above to true.  It then stays for the rest
      // of the session until they set it to false.
  }
  #endif
 // ...
}

Ich kann in C # nicht genau dasselbe tun, da es keine lokale Statik gibt.

Frage : Was ist der beste Weg, um dies in C # zu erreichen?

  1. Sollte ich ein statisches Feld für private Klassen mit C # -Vorprozessoranweisungen ( #if/#endif DEBUG) verwenden?
  2. Sollte ich das Conditional-Attribut (um den Code zu speichern) und dann ein statisches Feld für eine private Klasse verwenden ( nicht von C # -Vorprozessoranweisungen umgeben #if/#endif DEBUG?).
  3. Etwas anderes?
Matt Smith
quelle

Antworten:

145

Eine Instanzvariable wäre wahrscheinlich der Weg, um das zu tun, was Sie wollen. Sie können es statisch machen, den gleichen Wert für die Lebensdauer des Programms beizubehalten (oder den Thread abhängig von Ihrem statischen Speichermodell), oder es zu einer normalen Instanzvariable machen, um es über die Lebensdauer einer Objektinstanz zu steuern. Wenn diese Instanz ein Singleton ist, verhalten sie sich genauso.

#if DEBUG
private /*static*/ bool s_bDoDebugOnlyCode = false;
#endif

void foo()
{   
  // ...
#if DEBUG
  if (s_bDoDebugOnlyCode)
  {
      // Code here gets executed only when compiled with the DEBUG constant, 
      // and when the person debugging manually sets the bool above to true.  
      // It then stays for the rest of the session until they set it to false.
  }
#endif
 // ...
}

Um vollständig zu sein, werden Pragmas (Präprozessor-Direktiven) als ein bisschen umständlich angesehen, um den Programmfluss zu steuern. .NET hat eine integrierte Antwort für die Hälfte dieses Problems mit dem Attribut "Bedingt".

private /*static*/ bool doDebugOnlyCode = false; 
[Conditional("DEBUG")]
void foo()
{   
  // ...    
  if (doDebugOnlyCode)
  {
      // Code here gets executed only when compiled with the DEBUG constant, 
      // and when the person debugging manually sets the bool above to true.  
      // It then stays for the rest of the session until they set it to false.
  }    
  // ...
}

Keine Pragmas, viel sauberer. Der Nachteil ist, dass Conditional nur auf Methoden angewendet werden kann. Sie müssen sich also mit einer booleschen Variablen befassen, die in einem Release-Build nichts bewirkt. Da die Variable nur zum Umschalten vom VS-Ausführungshost vorhanden ist und in einem Release-Build ihr Wert keine Rolle spielt, ist sie ziemlich harmlos.

KeithS
quelle
2
Endlich - jemand, der die ganze Frage gelesen hat . Danke, okay - es schien eine langwierige Lösung zu sein (die beiden Präprozessorabschnitte müssen vorhanden sein), aber vielleicht ist es das Beste, was C # für das tun kann, was ich will.
Matt Smith
6
meh. Ich würde das nicht als langwierig bezeichnen, nur weil Sie zwei weitere Zeilen der Präprozessor-Direktive hinzufügen.
KeithS
4
Vielen Dank, Patrick, für die Ablehnung einer 3-jährigen akzeptierten Antwort zugunsten einer Antwort, die nicht das gesamte Problem löst. Das bedingte Attribut verhindert nur, dass die Methode im Nicht-Debug-Modus ausgeführt wird. Das OP wollte nicht nur das, sondern auch den Code mit dem Debugger "einschalten" können. Und Gokkors verwendetes Tag wird nicht kompiliert.
KeithS
2
Beachten Sie, dass der Präprozessor Ihnen mitteilt, ob das Programm im Debug-Modus kompiliert wird, nicht jedoch, ob der Debugger tatsächlich ausgeführt wird.
Shane
64

Was Sie suchen, ist

[ConditionalAttribute("DEBUG")]

Attribut.

Wenn Sie zum Beispiel eine Methode schreiben wie:

[ConditionalAttribute("DEBUG")]
public static void MyLovelyDebugInfoMethod(string message)
{
    Console.WriteLine("This message was brought to you by your debugger : ");
    Console.WriteLine(message);
}

Jeder Aufruf dieser Methode in Ihrem eigenen Code wird nur im Debug-Modus ausgeführt. Wenn Sie Ihr Projekt im Release-Modus erstellen, wird sogar der Aufruf der "MyLovelyDebugInfoMethod" ignoriert und aus Ihrer Binärdatei gelöscht.

Und noch etwas: Wenn Sie feststellen möchten, ob Ihr Code gerade zum Zeitpunkt der Ausführung debuggt oder nicht, können Sie auch überprüfen, ob der aktuelle Prozess von einer JIT verknüpft ist. Aber das ist alles zusammen ein anderer Fall. Schreiben Sie einen Kommentar, wenn Sie dies versuchen.

Gokkor
quelle
3
Bei Verwendung von Attribute müssen Sie nicht das Suffix "Attribute" schreiben. Conditional = ConditionalAttribute. Eine Attributklasse sollte mit "Attribut" enden, kann jedoch weggelassen werden, wenn sie als Attribut im Code verwendet wird. Es ist leichter zu lesen, wenn das Suffix weggelassen wird.
Eric Ouellet
23

Sie können dies versuchen, wenn Sie den Code nur ausführen müssen, wenn Sie einen Debugger an den Prozess angehängt haben.

if (Debugger.IsAttached)
{
     // do some stuff here
}
Wir s
quelle
Danke dir! Genau das wollte ich: Führen Sie am Ende eine Console.ReadLine () aus, um zu verhindern, dass das Konsolenfenster beim Debuggen geschlossen wird.
VVS
4

Ich denke, es kann erwähnenswert sein, dass [ConditionalAttribute]sich das im System.Diagnostics;Namespace befindet. Ich bin ein bisschen gestolpert, als ich bekam:

Error 2 The type or namespace name 'ConditionalAttribute' could not be found (are you missing a using directive or an assembly reference?)

nach dem ersten Gebrauch (ich dachte, es wäre in gewesen System).

XyberICE
quelle
3

Wenn Sie wissen möchten, ob beim Debuggen, überall im Programm. Benutze das.

Deklarieren Sie die globale Variable.

bool isDebug=false;

Erstellen Sie eine Funktion zum Überprüfen des Debug-Modus

[ConditionalAttribute("DEBUG")]
    public static void isDebugging()
    {
        isDebug = true;
    }

Rufen Sie in der Initialisierungsmethode die Funktion auf

isDebugging();

Jetzt im gesamten Programm. Sie können nach Debugging suchen und die Vorgänge ausführen. Hoffe das hilft!

Mohamed Alikhan
quelle
1
AFAIK: Dies und Varianten hiervon sind nur ein sicherer Weg, um festzustellen, ob ein Programm mit dem gesetzten Debug-Flag kompiliert wurde .
LosManos