2010-09-28 22 views
7

ConditionalAttribute वर्ग पर प्रलेखन के अनुसार:क्या सशर्त एट्रिब्यूट पूरी लाइनों को बाहर निकालना है, या सिर्फ विधि कॉल?

एक विधि के लिए ConditionalAttribute लागू करने compilers कि विधि करने के लिए एक कॉल नहीं किया जा माइक्रोसॉफ्ट मध्यवर्ती भाषा (MSIL) में संकलित किया जाना चाहिए करने के लिए इंगित करता है जब तक सशर्त संकलन प्रतीक जो सशर्त एट्रिब्यूट के साथ से जुड़ा हुआ है परिभाषित किया गया है।

मेरे लिए यह कह रहा है कि Conditional विशेषता केवल व्यक्तिगत विधि कॉल स्तर पर व्यवहार को बदल देती है।

class InstanceType 
{ 
    public InstanceType DoSideEffects() 
    { 
     Console.WriteLine("Side effects!"); 
     return this; 
    } 

    public InstanceType DoMoreSideEffects() 
    { 
     Console.WriteLine("More side effects!"); 
     return this; 
    } 

    [Conditional("DEBUG")] 
    public void ConditionalMethod() 
    { 
     Console.WriteLine("Conditional method run."); 
    } 
} 

class Program 
{ 
    static void Main() 
    { 
     var x = new InstanceType(); 

     // The compiler appears to strip out this entire line 
     // in a Release build. 
     x.DoSideEffects().DoMoreSideEffects().ConditionalMethod(); 

     var y = new InstanceType(); 

     // When each method call appears on its own line, 
     // the first two methods are included as expected. 
     y.DoSideEffects(); 
     y.DoMoreSideEffects(); 
     y.ConditionalMethod(); 
    } 
} 

डीबग के आउटपुट की तुलना करें और रिलीज बनाता है:

 
DEBUG     RELEASE 
Side effects!   Side effects! 
More side effects!  More side effects! 
Conditional method run. 
Side effects! 
More side effects! 
Conditional method run. 

इस व्यवहार कहीं निर्दिष्ट है लेकिन निम्नलिखित कोड का टुकड़ा पर विचार? मैंने सोचा था कि दोनों निर्माणों को "सशर्त विधि चलाने" पढ़ने वाली रेखाओं को छोड़कर एक ही आउटपुट होना चाहिए था।

+0

'की [सशर्त] मेरी समझ' तुम्हारा के रूप में ही है, और मुझे लगता है कि आप यहां अनुकूलन के प्रभाव को देख रहे हैं। आईएल रिलीज मोड में कैसा दिखता है? –

+0

दिलचस्प रूप से पर्याप्त, यहां तक ​​कि विजुअल स्टूडियो (या यह रीशर्पर है?) यदि आप DEBUG को परिभाषित नहीं करते हैं तो पहले मामले में पूरी लाइन ग्रे/अप्रयुक्त रंगों को रंग दें। जबकि दूसरे में, यह केवल ConditionalMethod() ग्रे/अप्रयुक्त कॉल को कॉल करता है। –

+0

संभावित डुप्लिकेट [.NET की सशर्त विशेषता क्यों साइड-इफेक्ट्स को हटाया जा सकता है?] (Http://stackoverflow.com/questions/410865/why-does-nets-conditional-attribute-cause-side-effects-to -बे-हटाया गया) –

उत्तर

2

इंटेरेसस्टिंग सुविधा :-) मैंने कभी यह नहीं देखा है।

मैंने आईएल पर एक नज़र डाली है। यह व्यवहार (संकलन प्रक्रिया) की व्याख्या नहीं करता है, लेकिन यह वैसे भी परिणाम दस्तावेज करता है, मुझे विश्वास है।

पूरे सी # कोड लाइन स्पष्ट रूप से आईएल में बाहर छोड़ दिया है:

  • डीबग संकलन में एक नया वस्तु बनाई गई है (एक्स चर) में, संग्रहीत किए गए स्थान 0 और लोड पर । बाद में तीन तरीकों से लागू होते हैं क्रमिक: DoSideEffects(), DeMoreSideEffects(), और ConditionalMethod()
  • विज्ञप्ति संकलन में चर अभी भी बनाया जाता है, लेकिन जब से यह आवश्यक नहीं है, इसे तुरंत pop'ed है । इसके बजाय y चर स्थान 0 पर संग्रहीत किया जाता है और लोड किया जाता है।

मेरे लिए, यह वास्तव में एक बग की तरह दिखता है। ऐसा लगता है कि आईएल में ConditionalMethod() कॉल को बाहर करना संभव होगा। लेकिन ऐसा लगता है कि आप सही हैं, कि पूरी लाइन छोड़ दी गई है।

// DEBUG compilation 
.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  58 (0x3a) 
    .maxstack 1 
    .locals init (class ConsoleApplication3.InstanceType V_0, 
      class ConsoleApplication3.InstanceType V_1) 
    IL_0000: nop 
    IL_0001: newobj  instance void ConsoleApplication3.InstanceType::.ctor() 
    IL_0006: stloc.0 
    IL_0007: ldloc.0 
    IL_0008: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoSideEffects() 
    IL_000d: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoMoreSideEffects() 
    IL_0012: callvirt instance void ConsoleApplication3.InstanceType::ConditionalMethod() 
    IL_0017: nop 
    IL_0018: newobj  instance void ConsoleApplication3.InstanceType::.ctor() 
    IL_001d: stloc.1 
    IL_001e: ldloc.1 
    IL_001f: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoSideEffects() 
    IL_0024: pop 
    IL_0025: ldloc.1 
    IL_0026: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoMoreSideEffects() 
    IL_002b: pop 
    IL_002c: ldloc.1 
    IL_002d: callvirt instance void ConsoleApplication3.InstanceType::ConditionalMethod() 
    IL_0032: nop 
    IL_0033: call  valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() 
    IL_0038: pop 
    IL_0039: ret 
} // end of method Program::Main 

// RELEASE compilation 
.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  33 (0x21) 
    .maxstack 1 
    .locals init ([0] class ConsoleApplication3.InstanceType y) 
    IL_0000: newobj  instance void ConsoleApplication3.InstanceType::.ctor() 
    IL_0005: pop 
    IL_0006: newobj  instance void ConsoleApplication3.InstanceType::.ctor() 
    IL_000b: stloc.0 
    IL_000c: ldloc.0 
    IL_000d: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoSideEffects() 
    IL_0012: pop 
    IL_0013: ldloc.0 
    IL_0014: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoMoreSideEffects() 
    IL_0019: pop 
    IL_001a: call  valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() 
    IL_001f: pop 
    IL_0020: ret 
} // end of method Program::Main 
0

क्षमा करें, इस तरह की एक पुरानी पोस्ट खींचें, लेकिन मुझे बस एक ही चीज़ का सामना करना पड़ा और यह इस मुद्दे का एकमात्र चर्चा था जिसे मैं पा सकता था।

मेरे पास क्या चल रहा है के बारे में एक झुकाव है। [Conditional]ConditionalMethod()पर कॉल को पर किसी भी अभिव्यक्ति को पारित करने वाले पैरामीटर के रूप में कार्य करने के लिए कॉल कर रहा है (दस्तावेज़ीकरण के अनुसार, और ऊपर दिए गए अन्य थ्रेड)।

मेरा अनुमान है कि निहित this पैरामीटर का बिल्कुल वैसा ही व्यवहार किया जा रहा है। x.DoSideEffects().DoMoreSideEffects().ConditionalMethod(); पंक्ति में this के रूप में पारित अभिव्यक्ति x.DoSideEffects().DoMoreSideEffects() है जो साइड इफेक्ट्स को समाप्त करने, कर्तव्यपूर्वक छीन ली गई है।

अगर हम छद्म कोड जहां हम स्पष्ट रूप से प्रत्येक विधि के लिए पहले पैरामीटर के रूप this पारित में पुनर्लेखन यह बहुत स्पष्ट हो जाता है:

ConditionalMethod(DoMoreSideEffects(DoSideEffects(x)));