C # if / then debug vs release yönergeleri


433

Çözüm özelliklerinde, tek ve tek projem için "serbest bırakma" olarak ayarlanmış Yapılandırma var.

Ana rutinin başında, bu kodu var ve "Mode = Debug" gösteriyor. Ayrıca en üstte şu iki satır var:

#define DEBUG 
#define RELEASE

Doğru değişkeni mi test ediyorum?

#if (DEBUG)
            Console.WriteLine("Mode=Debug"); 
#elif (RELEASE)
            Console.WriteLine("Mode=Release"); 
#endif

Amacım, hata ayıklama ve bırakma moduna göre değişkenler için farklı varsayılanlar ayarlamaktır.


13
HEM hata ayıklama ve serbest bırakmayı tanımlıyorsunuz.
Eric Dahlvang

Yanıtlar:


719

DEBUG/ _DEBUGzaten VS'de tanımlanmış olmalıdır.

#define DEBUGKodunuzdaki kodu kaldırın . Ön işlemcileri, ilgili yapı için yapı yapılandırmasında ayarlayın.

O "Mod = Debug" yazdırır nedeni, aramalarınızdan olduğunu #defineve daha sonra atlar elif.

Kontrol etmenin doğru yolu:

#if DEBUG
    Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif

Kontrol etme RELEASE.


77
Ben sadece bir RELEASE kontrol etmek istedim, o zaman bunu yapabilir: #if! DEBUG

3
Neden #ifolmasın #ifdef?
Bob Stein

23
@ BobStein-VisiBone Burada C # hakkında konuştuğumuzu hatırla, C değil #ifdefC / C ++ ön işlemcisine özgüdür, C # kullanımını zorunlu kılar #if.
jduncanator

27
@Jess, bunun Visual Studio'nun grileştirmeyi yaptığına inanıyorum, ReSharper değil
Dakotah Hicock

1
@DakotahHicock Doğru, resharper kullanmıyorum ve VS grileştiriyor.
17'de makoshichi

294

Varsayılan olarak, proje Debug modunda derlenmişse Visual Studio DEBUG'ı tanımlar ve Release modundaysa tanımlamaz. RELEASE, Release modunda varsayılan olarak tanımlanmamıştır. Bunun gibi bir şey kullanın:

#if DEBUG
  // debug stuff goes here
#else
  // release stuff goes here
#endif

Yalnızca yayın modunda bir şey yapmak istiyorsanız:

#if !DEBUG
  // release...
#endif

Ayrıca, yalnızca belirli bir sembol tanımlandığında çalıştırılmasını sağlamak için [Conditional("DEBUG")]dönen yöntemlerde öznitelik kullanabileceğinizi voidbelirtmek gerekir. Sembol tanımlanmamışsa, derleyici bu yöntemlere yapılan tüm çağrıları kaldıracaktır:

[Conditional("DEBUG")]
void PrintLog() {
    Console.WriteLine("Debug info");
}

void Test() {
    PrintLog();
}

6
Müthiş cevap, takdir.
Duy Tran

210

Ben #definedirektifleri arama üzerinde böyle kontrol tercih ederim :

if (System.Diagnostics.Debugger.IsAttached)
{
   //...
}
else
{
   //...
}

Elbette ki, hata ayıklama modunda bir şey derleyebilir ve dağıtabilirsiniz, ancak yine de hata ayıklayıcı takılı değildir.


1
Teşekkür ederim! "#Defines" in ne olduğunu henüz bilmiyorum, bu yüzden bu harika bir çözüm!
Tim

Ve benim durumum, bu tam olarak istediğimi yapıyor. Aslında bağlı bir hata ayıklayıcı varsa bilmek istiyorum, çünkü bağlı bir hata ayıklayıcı varsa idam istemiyorum bazı kod var biliyorum. Bu harika!
JFTxJ

1
Şahsen #IF DEBUGkod hata ayıklama durumunda kullanmak gibi sürmemelidir. Üretim kodu için yukarıdakileri kullanmayı kabul ediyorum.
Coops

10
Bunu kullanmak yerine geri çekmek #DEBUG, eğer bu deyim kodunuzda ise ve her zaman #DEBUGyanıtın derleme zamanında uygulanamayan kodu kaldırdığı için kontrol edilir ve böylece çalışma zamanı kontrolünüz yoktur. exe (ya da derlediğiniz her şey) daha küçüktür.
Dan

1
@ user34660. Belirtilen sorunun cevabı "hayır" dır, ki bu kimseye gerçekten yardımcı olmaz.
Steve Smith

51

Özellikle hata ayıklama geçişleri nerede sorunları verir, ancak dikkatli değilseniz sürüm yapıları başarısız olduğu gibi özellikle kod tabanı çevresinde yayılırsanız #if şeyler büyük bir hayranı değilim.

İşte burada ne ( C # # ifdef esinlenerek) ile geldim :

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;
    }
}

2
Hey şimdi, bu oldukça yaratıcı. Özelliği ayarlamak için özniteliği kullanmanızı seviyorum.
kenchilada

3
Bunun avantajı, Resharper'da geçerli koşullu kuruluma göre kodunuzu bozabilecek hataları yeniden düzenleyerek çarpmamanızdır.
Jafin

3
Bu gibi ama neden bir hizmet yerine bu tek bir uygulama oluşturmak merak ediyorum. Sisteme özgüdür ve her yere enjekte etme konusunda endişelenmenize gerek kalmaz. (bu işlevselliğin uygulanmasının farklı olacağı bir senaryo tasavvur edebilir misiniz?
BastanteCaro

1
Aslında şu anda kullandığım tek bir sınıfta tek bir hizmet ve hizmet uygulamam var, bu yüzden onu hangi yoldan kullanacağınızı seçme şansınız var ... her iki kod yolunu da test edebilirsiniz ...
Tod Thomson

Neden DebuggingServicestatik bir sınıf olmadığını ve neden bir arayüze ihtiyacınız olduğunu merak ediyorum. Bu bir IoC konteyneriyle kullanmakla ilgili bir şey mi?
Ben

23
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='

Yöntemin Debug.Assertkoşullu özelliği vardır DEBUG. O tanımlı değilse, çağrı ve atama isDebug = true edilir elimine :

Sembol tanımlanmışsa, çağrı dahil edilir; aksi takdirde çağrı (çağrının parametrelerinin değerlendirilmesi dahil) ihmal edilir.

Eğer DEBUGtanımlanmışsa, isDebugolarak ayarlanır true(ve Debug.Assertbu durumda hiçbir şey yapmaz) iletilir .


Bu da oldukça yaratıcı bir çözüm. :)
Jack

Güzel. Hata Ayıkla ve Bırak arasında değişmesi gereken bir yineleme değişkeni için ... var iterations = 10; Debug.Assert((iterations = Int32.MaxValue) > 0);
Matt Davis

19

Derleme türü için tanımlanan değişkeni kullanmaya çalışıyorsanız, iki satırı kaldırmanız gerekir ...

#define DEBUG  
#define RELEASE 

... bunlar #if (DEBUG) öğesinin her zaman doğru olmasına neden olur .

Ayrıca RELEASE için varsayılan bir Koşullu derleme sembolü yoktur . Proje özelliklerine bir tanesini tanımlamak istiyorsanız, Oluştur sekmesine tıklayın ve ardından Genel başlığının altındaki Koşullu derleme sembolleri metin kutusuna RELEASE ekleyin .

Diğer seçenek bunu yapmak olurdu ...

#if DEBUG
    Console.WriteLine("Debug");
#else
    Console.WriteLine("Release");
#endif

7

Üstteki tanımlarınızı kaldırın

#if DEBUG
        Console.WriteLine("Mode=Debug"); 
#else
        Console.WriteLine("Mode=Release"); 
#endif

7

Ayrı bir sınıf yerine statik bir işlev olarak Tod Thomson tarafından cevap biraz değiştirilmiş (piç?) Sürümü (Ben zaten dahil bir viewutils sınıfından bir WebForm viewbinding olarak adlandırmak istedim).

public static bool isDebugging() {
    bool debugging = false;

    WellAreWe(ref debugging);

    return debugging;
}

[Conditional("DEBUG")]
private static void WellAreWe(ref bool debugging)
{
    debugging = true;
}

6

Proje Oluşturma Özellikleri'nde DEBUG sabitini tanımladığınızdan emin olun. Bu, etkinleştirecektir #if DEBUG. Önceden tanımlanmış bir RELEASE sabiti görmüyorum;

Proje Oluşturma Özellikleri'nde DEBUG sabitini tanımlama


5

NameSpace'in

using System.Resources;
using System.Diagnostics;

Yöntem

   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;
    }

3

Size çok zaman kazandırabilecek bir ipucu - bunu seçseniz bile unutmayın debug yapı yapılandırması altında seçseniz (vs2012 / 13 menüsünde BUILD => CONFIGURATION MANAGER altındadır) - bu yeterli değildir.

YAYINLA dikkat etmelisiniz Configuration, şöyle:

resim açıklamasını buraya girin


0

Bu COMPILER yönergelerinin amacı derleyiciye kod, hata ayıklama kodu, beta kodu veya belki de tüm son kullanıcılarınız için gerekli olan kodu içermemesini söylemektir. Bunları ihtiyaçlarınıza göre ekleyebilir veya kaldırabilirsiniz. Örneğin, bir AdDept olmayan AdDept ile birleşirse, kaynak kodunuzu değiştirmek zorunda kalmadan. Sonra yapılması gereken tek şey programın mevcut bir sürümünün derleyici seçenekleri özellikler sayfasına #AdDept yönergesini dahil etmek ve bir derleme ve wa la! birleştirilen programın kodu yaylanıyor !.

Ayrıca, prime time için hazır olmayan veya serbest bırakma zamanına kadar kodda etkin olamayan yeni bir işlem için bir bildirim kullanmak isteyebilirsiniz.

Her neyse, işte böyle yapıyorum.


0

Daha iyi bir yol düşünmeliyim. #İf bloklarının diğer konfigürasyonlarda etkili bir şekilde yorumlandığı bana şaştı (varsayalım DEBUGveya RELEASEherhangi bir sembolle doğru)

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");
        }

0

Tanımları kaldırın ve koşulun hata ayıklama modunda olup olmadığını kontrol edin. Direktifin yayın modunda olup olmadığını kontrol etmenize gerek yoktur.

Bunun gibi bir şey:

#if DEBUG
     Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.