Was ist bei einem großen Projekt besser zu verwenden und warum?
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
o
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Was ist bei einem großen Projekt besser zu verwenden und warum?
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
o
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Es kommt wirklich darauf an, was Sie erreichen wollen:
#if DEBUG
: Der hier enthaltene Code wird bei der Veröffentlichung nicht einmal die IL erreichen.[Conditional("DEBUG")]
: Dieser Code wird die IL erreichen, aber ruft auf. an die Methode wird ausgelassen, es sei denn, DEBUG ist beim Kompilieren des Aufrufers gesetzt.Ich persönlich benutze beides, je nach Situation:
Conditional("DEBUG") Beispiel: Ich verwende dies, damit ich nicht zurückgehen und meinen Code später während der Veröffentlichung bearbeiten muss, aber während der Fehlersuche möchte ich sicher sein, dass ich keine Tippfehler gemacht habe. Diese Funktion prüft, ob ich einen Eigenschaftsnamen richtig eingebe, wenn ich versuche, ihn in meinem INotifyPropertyChanged-Zeug zu verwenden.
[Conditional("DEBUG")]
[DebuggerStepThrough]
protected void VerifyPropertyName(String propertyName)
{
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
Debug.Fail(String.Format("Invalid property name. Type: {0}, Name: {1}",
GetType(), propertyName));
}
Sie sollten wirklich keine Funktion erstellen, die #if DEBUG
es sei denn, Sie sind bereit, jeden Aufruf dieser Funktion mit demselben #if DEBUG
:
#if DEBUG
public void DoSomething() { }
#endif
public void Foo()
{
#if DEBUG
DoSomething(); //This works, but looks FUGLY
#endif
}
gegen:
[Conditional("DEBUG")]
public void DoSomething() { }
public void Foo()
{
DoSomething(); //Code compiles and is cleaner, DoSomething always
//exists, however this is only called during DEBUG.
}
#if DEBUG Beispiel: Ich verwende dies, wenn ich versuche, verschiedene Bindungen für die WCF-Kommunikation einzurichten.
#if DEBUG
public const String ENDPOINT = "Localhost";
#else
public const String ENDPOINT = "BasicHttpBinding";
#endif
Im ersten Beispiel ist der Code zwar vorhanden, wird aber nur dann ignoriert, wenn DEBUG eingeschaltet ist. Im zweiten Beispiel wird die Konstante ENDPOINT auf "Localhost" oder "BasicHttpBinding" gesetzt, je nachdem, ob DEBUG eingestellt ist oder nicht.
Aktualisierung: Ich aktualisiere diese Antwort, um einen wichtigen und heiklen Punkt zu klären. Wenn Sie sich für die Verwendung der ConditionalAttribute
nicht vergessen, dass die Aufrufe während der Kompilierung ausgelassen werden, und nicht zur Laufzeit . Das heißt:
MyLibrary.dll
[Conditional("DEBUG")]
public void A()
{
Console.WriteLine("A");
B();
}
[Conditional("DEBUG")]
public void B()
{
Console.WriteLine("B");
}
Wenn die Bibliothek im Freigabemodus kompiliert wird (d.h. ohne DEBUG-Symbol), wird sie immer den Aufruf von B()
von innen A()
ausgelassen, auch wenn ein Aufruf von A()
ist enthalten, weil DEBUG in der aufrufenden Assembly definiert ist.
Die #if Debug für DoSomething muss nicht alle aufrufenden Anweisungen von #if DEBUG umgeben sein. Sie können entweder 1: nur #if DEBUG das Innere von DoSomething, oder, tun ein #else mit einer leeren Definition von DoSomething. Trotzdem hat mir Ihr Kommentar geholfen, den Unterschied zu verstehen, aber #if DEBUG muss nicht so hässlich sein, wie Sie gezeigt haben.
Wenn Sie nur #if DEBUG den Inhalt, die JIT kann immer noch einen Aufruf der Funktion, wenn Ihr Code läuft in einem Nicht-Debug-Build. Die Verwendung des Attributs Conditional bedeutet, dass das JIT weiß, dass es die Aufrufsite in einem Nicht-DEBUG-Build gar nicht ausgeben soll.
Die Bedingung schließt den Code nicht aus. Er markiert ihn mit Metadaten. Der DEBUG-Wert wird zur Kompilierzeit des CALLING-Codes abgeglichen. Dieser kann sich innerhalb oder außerhalb der Baugruppe befinden, die die markierte Methode enthält.
Nun, es ist erwähnenswert, dass sie keineswegs dasselbe bedeuten.
Wenn das DEBUG-Symbol nicht definiert ist, dann wird im ersten Fall das SetPrivateValue
selbst nicht aufgerufen wird... während es im zweiten Fall zwar existiert, aber jede Anrufer die ohne das DEBUG-Symbol kompiliert werden, werden diese Aufrufe weggelassen.
Wenn der Code und alle seine Aufrufer in der gleichen Assembly sind, ist dieser Unterschied menos wichtig - aber es bedeutet, dass Sie im ersten Fall également haben müssen #if DEBUG
um den aufrufen auch den Code.
Ich persönlich würde den zweiten Ansatz empfehlen - aber Sie müssen sich den Unterschied zwischen beiden klar vor Augen halten.
+1 für aufrufenden Code muss ebenfalls #if-Anweisungen enthalten. Das bedeutet, dass es eine Vermehrung von #if-Anweisungen geben wird...
Ich bin mir sicher, dass viele anderer Meinung sind, aber da ich als Entwickler ständig höre: "Aber das funktioniert doch auf meinem Rechner!", vertrete ich den Standpunkt, dass man beides so gut wie nie verwenden sollte. Wenn Sie wirklich etwas zum Testen und Debuggen brauchen, finden Sie einen Weg, diese Testbarkeit vom eigentlichen Produktionscode zu trennen.
Abstrahieren Sie die Szenarien mit Mocking in Unit-Tests, erstellen Sie einmalige Versionen von Dingen für einmalige Szenarien, die Sie testen wollen, aber fügen Sie keine Debug-Tests in den Code für Binärdateien ein, die Sie testen und für die Produktionsfreigabe schreiben. Diese Debug-Tests verbergen mögliche Fehler nur vor den Entwicklern, so dass sie erst später im Prozess gefunden werden.
Ich stimme Ihnen völlig zu, Jimmy. Wenn Sie DI und Mocking für Ihre Tests verwenden, warum sollten Sie #if debug
oder ein ähnliches Konstrukt in Ihrem Code?
Nicht nur zu Testzwecken, sondern auch in Debug-Builds setzen wir oft eine Standard-E-Mail an uns selbst, indem wir #if DEBUG
damit wir beim Testen eines Systems, das als Teil des Prozesses E-Mails übertragen muss, nicht versehentlich andere spammen. Manchmal sind das die richtigen Werkzeuge für den Job :)
Ich würde im Allgemeinen mit Ihnen übereinstimmen, aber wenn Sie sich in einer Situation befinden, in der die Leistung von größter Bedeutung ist, dann möchten Sie den Code nicht mit überflüssigen Protokollierungs- und Benutzerausgaben überladen, aber ich stimme zu 100% zu, dass sie niemals verwendet werden sollten, um das grundlegende Verhalten zu ändern
Zum ersten Beispiel, SetPrivateValue
nicht im Build vorhanden sein, wenn DEBUG
nicht definiert ist, mit dem zweiten Beispiel, ruft auf. a SetPrivateValue
im Build nicht vorhanden ist, wenn DEBUG
ist nicht definiert.
Im ersten Beispiel müssen Sie alle Aufrufe an SetPrivateValue
con #if DEBUG
auch.
Im zweiten Beispiel sind die Aufrufe an SetPrivateValue
wird weggelassen, aber beachten Sie, dass SetPrivateValue
selbst wird weiterhin kompiliert. Dies ist nützlich, wenn Sie eine Bibliothek erstellen, so dass eine Anwendung, die auf Ihre Bibliothek verweist, Ihre Funktion weiterhin verwenden kann (wenn die Bedingung erfüllt ist).
Wenn Sie die Aufrufe weglassen und den Platz des Aufrufenden sparen wollen, können Sie eine Kombination der beiden Techniken verwenden:
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
#if DEBUG
// method body here
#endif
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
20 Stimmen
Siehe blogs.msdn.com/b/ericlippert/archive/2009/09/10/ für einige Gedanken zu dieser Frage.
2 Stimmen
Können Sie auch dies verwenden: if (Debugger.IsAttached) {...}
1 Stimmen
Hinweis für Unity-Entwickler: DEBUG bedeutet im Editor oder in Entwicklungs-Builds. forum.unity.com/threads/
3 Stimmen
Für alle, die auf der Suche nach Eric Lipperts archivierter Blogpost ist nicht mehr auf msdn zu finden: archive.org hat alles für Sie
4 Stimmen
Eigentlich ist archive.org nicht nötig, @EricLippert hat seinen Blog hierher verlegt: ( ericlippert.com/2009/09/10/ )
1 Stimmen
@rold2007: Danke für den Link; ich verschiebe nach und nach alle alten Inhalte rüber, aber sie sind noch nicht da. Außerdem hat MSDN mein Blog-Archiv wiederhergestellt, was sehr nett von ihnen war.
0 Stimmen
@MicheldeRuiter: Der obige Link ( ericlippert.com/2009/09/10/ ) funktioniert für mich. Der Link blogs.msdn.com ist für immer defekt.