Którego lepiej użyć i dlaczego w dużym projekcie:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
lub
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
c#
debugging
preprocessor
debug-symbols
Lucas B.
źródło
źródło
Odpowiedzi:
To naprawdę zależy od tego, do czego zmierzasz:
#if DEBUG
: Kod tutaj nie dotrze nawet do IL przy wydaniu.[Conditional("DEBUG")]
: Ten kod dotrze do IL, jednak wywołania tej metody zostaną pominięte, chyba że DEBUGA zostanie ustawiona podczas kompilowania wywołującego.Osobiście korzystam z obu w zależności od sytuacji:
Warunkowy („DEBUG”) Przykład: używam tego, aby nie musiałem wracać i edytować kodu później podczas wydania, ale podczas debugowania chcę się upewnić, że nie napisałem żadnych literówek. Ta funkcja sprawdza, czy poprawnie wpisuję nazwę właściwości podczas próby użycia jej w moich elementach INotifyPropertyChanged.
Naprawdę nie chcesz tworzyć funkcji,
#if DEBUG
chyba że chcesz zawrzeć każde wywołanie tej funkcji tym samym#if DEBUG
:przeciw:
#if Przykład DEBUG: Używam tego, gdy próbuję skonfigurować różne wiązania dla komunikacji WCF.
W pierwszym przykładzie cały kod istnieje, ale jest po prostu ignorowany, chyba że DEBUG jest włączony. W drugim przykładzie stała ENDPOINT jest ustawiona na „Localhost” lub „BasicHttpBinding” w zależności od tego, czy ustawiono DEBUG, czy nie.
Aktualizacja: aktualizuję tę odpowiedź, aby wyjaśnić ważny i trudny punkt. Jeśli zdecydujesz się na użycie
ConditionalAttribute
, pamiętaj, że połączenia są pomijane podczas kompilacji, a nie w czasie wykonywania . To jest:MyLibrary.dll
Kiedy biblioteka jest kompilowana w trybie zwolnienia (tj. Bez symbolu DEBUG), na zawsze będzie
B()
w niejA()
pomijane wezwanie do , nawet jeśli wywołanie toA()
jest włączone, ponieważ DEBUG jest zdefiniowany w zestawie wywołującym.źródło
Warto zauważyć, że wcale nie mają na myśli tego samego.
Jeśli symbol DEBUG nie jest zdefiniowany, to w pierwszym przypadku
SetPrivateValue
sam nie będzie wywoływany ... podczas gdy w drugim przypadku będzie istniał, ale wszelkie wywołujące, które są skompilowane bez symbolu DEBUG, będą miały pominięte połączenia.Jeśli kod i wszystkie jego rozmówców są w tym samym montaż ta różnica jest mniej ważne - ale to oznacza, że w pierwszym przypadku również trzeba mieć
#if DEBUG
okolice wywołanie kodu, jak również.Osobiście poleciłbym drugie podejście - ale musisz zachować wyraźną różnicę między nimi.
źródło
Jestem pewien, że wielu się ze mną nie zgodzi, ale spędzając czas jako budowniczy, ciągle słysząc „Ale to działa na mojej maszynie!”, Uważam, że prawie nigdy nie powinieneś używać. Jeśli naprawdę potrzebujesz czegoś do testowania i debugowania, znajdź sposób na oddzielenie testowalności od rzeczywistego kodu produkcyjnego.
Streszczenie scenariuszy z kpiną w testach jednostkowych, stwórz jednorazowe wersje rzeczy dla jednorazowych scenariuszy, które chcesz przetestować, ale nie umieszczaj testów do debugowania w kodzie plików binarnych, które testujesz i piszesz w wersji produkcyjnej. Te testy debugowania po prostu ukrywają ewentualne błędy przed programistami, więc nie można ich znaleźć do późniejszego etapu.
źródło
#if debug
podobnej konstrukcji w swoim kodzie?#if DEBUG
aby uniknąć przypadkowego spamowania innych podczas testowania systemu, który musi przesyłać wiadomości e-mail w ramach tego procesu. Czasami są to odpowiednie narzędzia do pracy :)Ten może być również przydatny:
źródło
Debugger.IsAttached
należy go wywoływać w czasie wykonywania, nawet w kompilacjach wersji.W pierwszym przykładzie
SetPrivateValue
nie będzie istniał w kompilacji, jeśliDEBUG
nie jest zdefiniowany, w drugim przykładzie wywołania doSetPrivateValue
nie będą istnieć w kompilacji, jeśliDEBUG
nie zostaną zdefiniowane.Z pierwszego przykładu, będziesz musiał zawijać do jakichkolwiek rozmów
SetPrivateValue
z#if DEBUG
tak dobrze.W drugim przykładzie wywołania do
SetPrivateValue
zostaną pominięte, ale należy pamiętać, żeSetPrivateValue
nadal będzie się kompilować. Jest to przydatne, jeśli budujesz bibliotekę, więc aplikacja odwołująca się do twojej biblioteki może nadal korzystać z twojej funkcji (jeśli warunek jest spełniony).Jeśli chcesz pominąć połączenia i zaoszczędzić miejsce odbiorcy, możesz użyć kombinacji dwóch technik:
źródło
#if DEBUG
wokółConditional("DEBUG")
nie usunie połączenia do tej funkcji, to po prostu usuwa funkcję z IL alltogether, więc nadal masz połączenia do funkcji, która nie istnieje (błędy kompilacji).Załóżmy, że twój kod zawierał także
#else
instrukcję definiującą zerową funkcję stub, odnoszącą się do jednego z punktów Jona Skeeta. Istnieje druga ważna różnica między nimi.Załóżmy, że funkcja
#if DEBUG
lubConditional
istnieje w bibliotece DLL, do której odwołuje się główny plik wykonywalny projektu. Korzystając z#if
, ocena warunkowa zostanie przeprowadzona w odniesieniu do ustawień kompilacji biblioteki. Za pomocą tegoConditional
atrybutu zostanie przeprowadzona ocena warunkowa w odniesieniu do ustawień kompilacji wywołującego.źródło
Mam rozszerzenie SOAP WebService do rejestrowania ruchu sieciowego przy użyciu niestandardowego
[TraceExtension]
. Używam tego tylko do kompilacji Debugowania i pomijam kompilacje Release . Użyj,#if DEBUG
aby owinąć[TraceExtension]
atrybut, usuwając go w ten sposób z kompilacji wersji .źródło
Zwykle jest to potrzebne w Program.cs, gdzie chcesz zdecydować się na uruchomienie debugowania na kodzie innym niż debugowanie, a także zbyt często w usługach systemu Windows. Stworzyłem więc pole tylko do odczytu IsDebugMode i ustawiłem jego wartość w konstruktorze statycznym, jak pokazano poniżej.
źródło