डिबग बनाम रिलीज़ के लिए सी # यदि निर्देश / तो


432

समाधान गुणों में, मेरे पास एक और एकमात्र परियोजना के लिए "रिलीज" करने के लिए कॉन्फ़िगरेशन सेट है।

मुख्य दिनचर्या की शुरुआत में, मेरे पास यह कोड है, और यह "मोड = डीबग" दिखा रहा है। मेरे पास भी ये दो पंक्तियाँ हैं:

#define DEBUG 
#define RELEASE

क्या मैं सही चर का परीक्षण कर रहा हूं?

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

मेरा लक्ष्य डिबग बनाम रिलीज़ मोड के आधार पर चर के लिए अलग-अलग डिफ़ॉल्ट सेट करना है।


13
आप बीओटीएच डिबग और रिलीज को परिभाषित कर रहे हैं।
एरिक डहलवांग

जवाबों:


718

DEBUG/ _DEBUGवीएस में पहले से ही परिभाषित किया जाना चाहिए।

#define DEBUGअपने कोड में निकालें । उस विशिष्ट बिल्ड के लिए बिल्ड कॉन्फ़िगरेशन में प्रीप्रोसेसर सेट करें।

"मोड = डीबग" प्रिंट करने का कारण यह है कि आपकी वजह से #defineऔर फिर स्किप हो जाता है elif

जांच करने का सही तरीका है:

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

के लिए जाँच नहीं है RELEASE


77
मैं जोड़ना चाहता था कि अगर कोई केवल RELEASE के लिए जाँच करना चाहता है तो कोई भी ऐसा कर सकता है: #if! DEBUG

3
क्यों #ifऔर क्या नहीं #ifdef?
बॉब स्टीन

23
@ BobStein-VisiBone याद रखें कि हम C # के बारे में बात कर रहे हैं #ifdef, C, C / C ++ के प्रीप्रोसेसर के लिए विशिष्ट नहीं है, C # के उपयोग को अनिवार्य करता है #if
jduncanator

27
@ मुझे लगता है कि यह विजुअल स्टूडियो ग्रेइंग कर रहा है, न कि
रीशर

1
@DakotahHicock यह सही है, मैं resharper का उपयोग नहीं करता और VS इसे बाहर करता है।
मकोशिची

294

डिफ़ॉल्ट रूप से, Visual Studio DEBUG को परिभाषित करता है यदि प्रोजेक्ट को डिबग मोड में संकलित किया गया है और यदि यह रिलीज़ मोड में है तो इसे परिभाषित नहीं करता है। डिफ़ॉल्ट रूप से रिलीज़ मोड में परिभाषित नहीं किया गया है। कुछ इस तरह का उपयोग करें:

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

यदि आप केवल रिलीज़ मोड में कुछ करना चाहते हैं:

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

इसके अलावा, यह इंगित करने योग्य है कि आप उन [Conditional("DEBUG")]विधियों पर विशेषता का उपयोग कर सकते हैं जो voidकेवल एक निश्चित प्रतीक को परिभाषित करने पर उन्हें निष्पादित करने के लिए वापस आती हैं । संकलक उन तरीकों से सभी कॉल को हटा देगा यदि प्रतीक परिभाषित नहीं है:

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

void Test() {
    PrintLog();
}

6
बहुत बढ़िया जवाब, सराहना की।
दुई ट्रान

210

मैं #defineनिर्देशन की तलाश में इसे इस तरह जाँचना पसंद करता हूँ :

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

इस चेतावनी के साथ कि आप डिबग मोड में कुछ संकलित और तैनात कर सकते हैं, लेकिन फिर भी डिबगर संलग्न नहीं है।


1
धन्यवाद! मुझे अभी तक पता नहीं है कि "#defines" क्या हैं इसलिए यह एक बढ़िया उपाय है!
टिम

और मेरे मामले में, यह वही करता है जो मैं चाहता हूं। मैं वास्तव में जानना चाहता हूं कि क्या मेरा कोई डिबगर जुड़ा हुआ है, क्योंकि मुझे पता है कि मेरे पास कुछ कोड हैं जिन्हें मैं डिबगर से जुड़ा होने पर निष्पादित नहीं करना चाहता। यह कमाल का है!
JFTxJ

1
यदि व्यक्तिगत रूप #IF DEBUGसे डिबगिंग कोड की स्थिति में उपयोग करना पसंद है जो कि अंतिम नहीं होना चाहिए। उत्पादन कोड के लिए मैं उपरोक्त का उपयोग करने से सहमत हूं।
कोप

10
उपयोग करने के बजाय ऐसा करने के लिए ड्रा बैक यह #DEBUGहै कि यदि यह स्टेटमेंट आपके कोड में है और हमेशा चेक किया जाता है कि #DEBUGउत्तर कहां से कोड को हटाता है जो संकलन समय पर लागू नहीं होता है, तो आपके पास रन-टाइम चेक और आपका नहीं है। exe (या आप जो भी संकलन करते हैं) छोटा होता है।
दान

1
@ user34660। बताए गए प्रश्न का उत्तर "नहीं" है, जो वास्तव में किसी की मदद नहीं करता है।
स्टीव स्मिथ

51

मैं #if सामान का बहुत बड़ा प्रशंसक नहीं हूं, खासकर यदि आप इसे अपने कोड बेस के चारों ओर फैलाते हैं क्योंकि यह आपको समस्याएं देगा जहां डीबग पास बनाता है, लेकिन रिलीज बिल्ड विफल हो जाता है यदि आप सावधान नहीं हैं।

तो यहाँ मैं क्या लेकर आया हूँ ( C # में #ifdef से प्रेरित होकर ):

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
अरे अब, यह बहुत रचनात्मक है। मुझे संपत्ति सेट करने के लिए विशेषता का आपका उपयोग पसंद है।
केेंचिलाड़ा

3
इसका लाभ यह है कि रेस्पर में बग्स को फिर से चालू करने से नहीं मारा जा सकता है जो मौजूदा सशर्त सेटअप के आधार पर आपके कोड को गड़बड़ कर सकता है।
जफिन

3
मुझे यह पसंद है लेकिन मैं सोच रहा हूं कि एक सेवा के बजाय इसके लिए एक सिंगलटन कार्यान्वयन क्यों न बनाया जाए। यह सिस्टम विशिष्ट है और यह आपको हर जगह इसे इंजेक्ट करने के बारे में चिंता करने से रोकता है। (क्या आप एक ऐसे परिदृश्य की परिकल्पना कर सकते हैं, जहाँ इस कार्यक्षमता का क्रियान्वयन अलग हो?
बस्तोंकरो

1
मेरे पास वास्तव में एक वर्ग में एक सिंगलटन और सेवा कार्यान्वयन है जो मैं अभी उपयोग कर रहा हूं इसलिए आपको इसका उपयोग करने के लिए किस तरह का विकल्प मिलता है ... निश्चित रूप से सेवा कार्यान्वयन को "स्टब" करने में आसान होने का लाभ है कि आप दोनों कोड रास्तों का परीक्षण कर सकते हैं ...
टॉड थॉमसन

मैं सोच रहा हूं कि DebuggingServiceएक स्थिर वर्ग क्यों नहीं है और आपको इंटरफ़ेस की आवश्यकता क्यों है? क्या यह IoC कंटेनर के साथ उपयोग करने के लिए कुछ है?
बेन

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

विधि Debug.Assertमें सशर्त विशेषता है DEBUG। यदि यह परिभाषित नहीं है, तो कॉल और असाइनमेंट समाप्त होisDebug = true जाते हैं :

यदि प्रतीक परिभाषित किया गया है, तो कॉल शामिल है; अन्यथा, कॉल (कॉल के मापदंडों के मूल्यांकन सहित) को छोड़ दिया जाता है।

यदि DEBUGपरिभाषित किया गया है, (और उस मामले में कुछ भी नहीं करता है) के isDebugलिए सेट trueकिया गया है Debug.Assert, जो पास है।


यह भी एक सुंदर रचनात्मक समाधान है। :)
जैक

अच्छा लगा। एक परिवर्तनशील चर के लिए जिसे डिबग और रिलीज़ के बीच बदलने की जरूरत है ... var iterations = 10; Debug.Assert((iterations = Int32.MaxValue) > 0);
मैट डेविस

19

यदि आप बिल्ड प्रकार के लिए परिभाषित चर का उपयोग करने की कोशिश कर रहे हैं, तो आपको दो लाइनों को हटा देना चाहिए ...

#define DEBUG  
#define RELEASE 

... ये हमेशा के लिए #if (DEBUG) का कारण बनेंगे

इसके अलावा RELEASE के लिए एक डिफ़ॉल्ट सशर्त संकलन प्रतीक नहीं है । यदि आप प्रोजेक्ट प्रॉपर्टीज में जाना चाहते हैं, तो बिल्ड टैब पर क्लिक करें और फिर जनरल के तहत सशर्त संकलन प्रतीकों टेक्स्ट बॉक्स में RELEASE जोड़ें। शीर्षक के ।

ऐसा करने के लिए अन्य विकल्प होगा ...

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

7

शीर्ष पर अपने परिभाषित निकालें

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

7

टॉड थॉमसन द्वारा एक अलग वर्ग के बजाय एक स्थिर कार्य के रूप में उत्तर का थोड़ा संशोधित (संक्षिप्त)?

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

    WellAreWe(ref debugging);

    return debugging;
}

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

6

प्रोजेक्ट बिल्ड प्रॉपर्टीज में DEBUG स्थिरांक को परिभाषित करना सुनिश्चित करें। यह सक्षम करेगा #if DEBUG। मुझे एक पूर्व-परिभाषित RELEASE स्थिर दिखाई नहीं देता है, इसलिए इसका अर्थ यह हो सकता है कि DEBUG ब्लॉक में कुछ भी नहीं RELEASE मोड है।

प्रोजेक्ट बिल्ड प्रॉपर्टी में DEBUG स्थिरांक को परिभाषित करें


5

नाम स्थान

using System.Resources;
using System.Diagnostics;

तरीका

   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

एक टिप जो आपको बहुत समय बचा सकती है - यदि आप चुनते हैं तो भी इसे मत भूलना debug बिल्ड कॉन्फ़िगरेशन के तहत (vs2012 / 13 मेनू पर यह BUILD => CONFIGURATION MANAGER के तहत है) - यह पर्याप्त नहीं है।

आपको सार्वजनिक Configurationरूप से इस पर ध्यान देने की आवश्यकता है:

यहां छवि विवरण दर्ज करें


0

चूंकि इन COMPILER निर्देशों का उद्देश्य संकलक को कोड, डिबग कोड, बीटा कोड, या शायद कोड को शामिल करने के लिए बताना है, जो आपके सभी अंतिम उपयोगकर्ताओं द्वारा आवश्यक है, सिवाय उन विज्ञापन विभाग के, जो कि #Define AdDept कहते हैं। अपनी आवश्यकताओं के आधार पर उन्हें शामिल करने या हटाने में सक्षम हो। यदि कोई गैर AdDept AdDept में विलीन हो जाता है तो अपने स्रोत कोड को बदले बिना। तब जो कुछ करने की जरूरत है, वह प्रोग्राम के मौजूदा संस्करण के कंपाइलर ऑप्शंस प्रॉपर्टीज पेज में # एडेप्ट डायरेक्टिव को शामिल करना है और एक कंपाइल और वा ला करना है! विलय कार्यक्रम के कोड स्प्रिंग्स जिंदा!

आप एक नई प्रक्रिया के लिए एक घोषणापत्र का उपयोग करना चाह सकते हैं जो प्राइम टाइम के लिए तैयार नहीं है या जो कोड में सक्रिय नहीं हो सकता है जब तक कि इसे रिलीज़ करने का समय नहीं है।

किसी भी तरह, मैं इसे करता हूं।


0

मैं एक बेहतर तरीके के बारे में सोच रहा था। इसने मुझ पर यह आरोप लगाया कि #if ब्लॉक अन्य कॉन्फ़िगरेशन (प्रभावी रूप से DEBUGया RELEASEकिसी भी प्रतीक के साथ सच है) में प्रभावी ढंग से टिप्पणी करते हैं ।

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

परिभाषाएं निकालें और जांचें कि क्या सशर्त डिबग मोड पर है। आपको यह देखने की ज़रूरत नहीं है कि निर्देश रिलीज़ मोड पर है या नहीं।

कुछ इस तरह:

#if DEBUG
     Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.