कौन सा उपयोग करना बेहतर है, और क्यों, एक बड़ी परियोजना पर:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
या
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
कौन सा उपयोग करना बेहतर है, और क्यों, एक बड़ी परियोजना पर:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
या
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
जवाबों:
यह वास्तव में इस बात पर निर्भर करता है कि आप क्या करने जा रहे हैं:
#if DEBUG
: यहाँ कोड भी रिलीज़ पर IL तक नहीं पहुंचेगा।[Conditional("DEBUG")]
: यह कोड IL तक पहुंच जाएगा, हालाँकि कॉल करने के लिए संकलित होने पर DEBUG सेट होने तक विधि को कॉल छोड़ दिया जाएगा।व्यक्तिगत रूप से मैं स्थिति के आधार पर दोनों का उपयोग करता हूं:
सशर्त ("DEBUG") उदाहरण: मैं इसका उपयोग करता हूं ताकि मुझे वापस जाने और बाद में रिलीज के दौरान अपना कोड संपादित करने की आवश्यकता न हो, लेकिन डिबगिंग के दौरान मैं यह सुनिश्चित करना चाहता हूं कि मैंने कोई टाइपो नहीं बनाया। यह फ़ंक्शन यह जांचता है कि मैं अपने INotifyPropertyChanged सामान में इसका उपयोग करने का प्रयास करते समय एक संपत्ति का नाम सही प्रकार से लिखता हूं।
[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));
}
आप वास्तव में एक फ़ंक्शन का उपयोग नहीं करना चाहते #if DEBUG
हैं जब तक आप उस फ़ंक्शन के लिए हर कॉल को उसी के साथ लपेटने के लिए तैयार न हों #if DEBUG
:
#if DEBUG
public void DoSomething() { }
#endif
public void Foo()
{
#if DEBUG
DoSomething(); //This works, but looks FUGLY
#endif
}
बनाम:
[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 उदाहरण: WCF संचार के लिए अलग-अलग बाइंडिंग सेट करने का प्रयास करते समय मैं इसका उपयोग करता हूं।
#if DEBUG
public const String ENDPOINT = "Localhost";
#else
public const String ENDPOINT = "BasicHttpBinding";
#endif
पहले उदाहरण में, कोड सभी मौजूद है, लेकिन तब तक इसे अनदेखा किया जाता है जब तक DEBUG चालू नहीं होता है। दूसरे उदाहरण में, कास्ट ENDPOINT "लोकलहोस्ट" या "बेसिकहेटबाइंडिंग" पर सेट है, यह निर्भर करता है कि DEBUG सेट है या नहीं।
अपडेट: मैं एक महत्वपूर्ण और मुश्किल बिंदु को स्पष्ट करने के लिए इस उत्तर को अपडेट कर रहा हूं। यदि आप इसका उपयोग करना चुनते हैं ConditionalAttribute
, तो ध्यान रखें कि कॉल संकलन के दौरान छोड़ दिए जाते हैं, और रनटाइम नहीं । अर्थात्:
MyLibrary.dll
[Conditional("DEBUG")]
public void A()
{
Console.WriteLine("A");
B();
}
[Conditional("DEBUG")]
public void B()
{
Console.WriteLine("B");
}
जब लाइब्रेरी को रिलीज़ मोड (अर्थात कोई DEBUG प्रतीक) के विरुद्ध संकलित किया जाता है, तो इसमें हमेशा के लिए छोड़ दिया गया के B()
भीतर से कॉल होगा A()
, भले ही कोई कॉल A()
शामिल हो क्योंकि DEBUG को कॉलिंग असेंबली में परिभाषित किया गया है।
खैर, यह ध्यान देने योग्य है कि उनका मतलब एक ही चीज से बिल्कुल नहीं है।
यदि DEBUG प्रतीक को परिभाषित नहीं किया जाता है, तो पहले मामले में SetPrivateValue
स्वयं को कॉल नहीं किया जाएगा ... जबकि दूसरे मामले में यह मौजूद होगा, लेकिन जो भी कॉल DEBUG प्रतीक के बिना संकलित किए गए हैं, उन कॉलों को छोड़ दिया जाएगा।
यदि कोड और उसके सभी कॉलर एक ही असेंबली में हैं तो यह अंतर है कम महत्वपूर्ण नहीं है - लेकिन इसका मतलब है कि पहले मामले में आपको कॉलिंग कोड के आसपास भी होना चाहिए ।#if DEBUG
व्यक्तिगत रूप से मैं दूसरे दृष्टिकोण की सिफारिश करूंगा - लेकिन आपको उनके बीच अंतर को अपने सिर में रखने की आवश्यकता है।
मुझे यकीन है कि बहुत कुछ मेरे साथ असहमत होगा, लेकिन एक बिल्ड आदमी के रूप में लगातार समय सुनकर समय बिताया "लेकिन यह मेरी मशीन पर काम करता है!", मैं दृष्टिकोण लेता हूं कि आपको बहुत अधिक कभी भी उपयोग नहीं करना चाहिए। यदि आपको वास्तव में परीक्षण और डिबगिंग के लिए कुछ की आवश्यकता है, तो वास्तविक उत्पादन कोड से उस परीक्षण क्षमता को अलग करने का एक तरीका निकालें।
यूनिट परीक्षणों में मॉकिंग के साथ परिदृश्यों को सार करें, एक ऑफ परिदृश्यों के लिए चीजों के एक संस्करण को बंद करें जिसे आप परीक्षण करना चाहते हैं, लेकिन बायनेरिज़ के लिए कोड में डिबग के लिए परीक्षण न डालें, जिसे आप परीक्षण और उत्पादन रिलीज के लिए लिखते हैं। ये डिबग परीक्षण सिर्फ देवों से संभावित कीड़े छिपाते हैं ताकि बाद में इस प्रक्रिया में उन्हें न मिले।
#if debug
अपने कोड में किसी भी समान निर्माण की आवश्यकता क्यों होगी ?
#if DEBUG
ताकि हम एक सिस्टम का परीक्षण करते समय गलती से दूसरों को स्पैम न करें जो प्रक्रिया के भाग के रूप में ईमेल को प्रसारित करना चाहिए। कभी-कभी ये नौकरी के लिए सही उपकरण हैं :)
यह एक उपयोगी हो सकता है:
if (Debugger.IsAttached)
{
...
}
Debugger.IsAttached
रिलीज बिल्ड में भी रनटाइम पर कॉल किया जाना चाहिए।
पहला उदाहरण के साथ, SetPrivateValue
निर्माण में मौजूद नहीं होगा अगर DEBUG
परिभाषित नहीं है, दूसरे उदाहरण के साथ, कॉल करने के लिए SetPrivateValue
निर्माण में मौजूद नहीं होगा अगर DEBUG
परिभाषित नहीं है।
पहले उदाहरण के साथ, आपको किसी भी कॉल को SetPrivateValue
साथ #if DEBUG
ही लपेटना होगा ।
दूसरे उदाहरण के साथ, कॉल को SetPrivateValue
छोड़ दिया जाएगा, लेकिन ध्यान रखें कि SetPrivateValue
खुद को अभी भी संकलित किया जाएगा। यदि आप एक पुस्तकालय का निर्माण कर रहे हैं तो यह उपयोगी है, इसलिए आपके पुस्तकालय को संदर्भित करने वाला एप्लिकेशन अभी भी आपके फ़ंक्शन का उपयोग कर सकता है (यदि शर्त पूरी हो गई है)।
यदि आप कॉल को छोड़ना चाहते हैं और कैली की जगह बचाना चाहते हैं, तो आप दो तकनीकों के संयोजन का उपयोग कर सकते हैं:
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
#if DEBUG
// method body here
#endif
}
#if DEBUG
चारों ओर लपेटने Conditional("DEBUG")
से उस फ़ंक्शन के कॉल नहीं हटाए जाते हैं, यह केवल IL से फ़ंक्शन को पूरी तरह से हटा देता है, इसलिए आप अभी भी फ़ंक्शन को कॉल कर रहे हैं जो मौजूद नहीं है (संकलन त्रुटियां)।
चलिए मान लेते हैं कि आपके कोड में एक #else
स्टेटमेंट भी था , जिसमें जॉन स्केट के बिंदुओं में से एक को संबोधित करते हुए एक अशक्त कार्य को परिभाषित किया गया था । दोनों के बीच एक दूसरा महत्वपूर्ण अंतर है।
मान लीजिए #if DEBUG
या Conditional
फ़ंक्शन एक DLL में मौजूद है जिसे आपके मुख्य प्रोजेक्ट द्वारा निष्पादित किया गया है। #if
मूल्यांकन का उपयोग करके , पुस्तकालय के संकलन सेटिंग्स के संबंध में सशर्त का मूल्यांकन किया जाएगा। Conditional
विशेषता का उपयोग करके , इनवोकलर के संकलन सेटिंग्स के संबंध में सशर्त का मूल्यांकन किया जाएगा।
मेरे पास एक कस्टम का उपयोग करके नेटवर्क ट्रैफ़िक लॉग करने के लिए SOAP WebService एक्सटेंशन है [TraceExtension]
। मैं इसे केवल डीबग बिल्ड और रिलीज़ बिल्ड से छोड़ देता हूं । का प्रयोग करें #if DEBUG
रैप करने के लिए [TraceExtension]
इस प्रकार विशेषता से इसे हटाने के रिलीज बनाता है।
#if DEBUG
[TraceExtension]
#endif
[System.Web.Service.Protocols.SoapDocumentMethodAttribute( ... )]
[ more attributes ...]
public DatabaseResponse[] GetDatabaseResponse( ...)
{
object[] results = this.Invoke("GetDatabaseResponse",new object[] {
... parmeters}};
}
#if DEBUG
[TraceExtension]
#endif
public System.IAsyncResult BeginGetDatabaseResponse(...)
#if DEBUG
[TraceExtension]
#endif
public DatabaseResponse[] EndGetDatabaseResponse(...)
आमतौर पर आपको Program.cs में इसकी आवश्यकता होगी जहां आप या तो डिबग को गैर-डिबग कोड पर चलाने का निर्णय लेना चाहते हैं और वह भी ज्यादातर विंडोज सेवाओं में। इसलिए मैंने एक पठनीय क्षेत्र IsDebugMode बनाया और नीचे दिए गए चित्र के अनुसार स्थिर कंस्ट्रक्टर में इसका मान सेट किया।
static class Program
{
#region Private variable
static readonly bool IsDebugMode = false;
#endregion Private variable
#region Constrcutors
static Program()
{
#if DEBUG
IsDebugMode = true;
#endif
}
#endregion
#region Main
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
if (IsDebugMode)
{
MyService myService = new MyService(args);
myService.OnDebug();
}
else
{
ServiceBase[] services = new ServiceBase[] { new MyService (args) };
services.Run(args);
}
}
#endregion Main
}