2009-10-28 23 views
13

यह Calling a method with ref or out parameters from an anonymous methodअज्ञात विधि में आउट पैरामीटर की अनुमति क्यों नहीं है?

के शिकार मैं सोच रहा हूँ क्यों बाहर मापदंडों गुमनाम तरीकों के भीतर की अनुमति नहीं है नहीं है। रेफरी पैरामीटर मुझे थोड़ा और समझ में नहीं आता है, लेकिन पैरामीटर जितना अधिक नहीं है।

इस

+0

मुझे आश्चर्य है कि आप कभी भी विधि विधि के बाहर एक अज्ञात प्रकार क्यों पारित करेंगे, जब तक कि आप प्रतिबिंब की खुशी को सीखना नहीं चाहते हैं। – Will

+0

क्या मूल लिंक प्रश्न पर यह उत्तर पर्याप्त रूप से इसका उत्तर नहीं देता है? http://stackoverflow.com/questions/801147/scope-of-anonymous-methods/801563#801563 –

+1

@Will: इसका अनाम प्रकारों से कोई लेना देना नहीं है। – SLaks

उत्तर

28

कुछ मायनों यह एक शिकार है पर अपने विचारों को क्या कर रहे हैं। Out पैरामीटर ref पैरामीटर हैं। सी # भाषा द्वारा उपयोग किए जाने वाले मूल्य पर बस एक अतिरिक्त विशेषता है। उन्हें अस्वीकार करने का कारण ref पैरामीटर के समान सटीक है।

यहां समस्या अज्ञात विधि के भीतर अज्ञात विधि के बाहर घोषित मूल्य का उपयोग करने के प्रभाव से उत्पन्न होती है। ऐसा करने से लैम्ब्डा के भीतर मूल्य कैप्चर होगा और आवश्यकता से बाहर मनमाने ढंग से वर्तमान कार्यकाल से परे अपने जीवनकाल का विस्तार होगा। यह out पैरामीटर के साथ संगत नहीं है जिसमें एक निश्चित जीवनकाल है।

उदाहरण के लिए कल्पना करें कि out पैरामीटर स्टैक पर स्थानीय चर से संदर्भित है। लैम्ब्डा भविष्य में किसी भी मनमानी बिंदु पर निष्पादित कर सकता है और इसलिए उस स्टैक फ्रेम को वैध नहीं होने पर निष्पादित किया जा सकता है। out पैरामीटर का मतलब क्या होगा?

+1

+1 आपके पिछले पैराग्राफ के समान उदाहरण टाइप करना शुरू कर दिया था। मुझे परेशान करने के लिए धन्यवाद :) –

+0

दूसरा अनुच्छेद लाइटबुल चालू कर दिया। धन्यवाद @ जेरेडपायर! –

+0

लेकिन क्या यह किसी अन्य प्रकार के चर पर लागू नहीं होगा? मेरा मतलब है, अगर मैं एक लैम्ब्डा अभिव्यक्ति के अंदर एक चर का उपयोग करता हूं जो ढेर में स्थित है, तो बस कुछ फ़ील्ड तक पहुंचें। यदि लैम्बडा एक्सप्रेसऑन निष्पादित करता है जब स्टैक अब मान्य नहीं होता है, तो क्या ऑब्जेक्ट पहले ही एकत्र नहीं किया जा सकता है? यदि ऐसा नहीं है, तो कचरा कलेक्टर उस वस्तु को कब एकत्र करेगा? –

6

इस तथ्य से कोई लेना देना मूल रूप से है कि एक गुमनाम प्रतिनिधि/लैम्ब्डा भाव के मापदंडों, पर कब्जा कर लिया चर, और ref/out चर पर कब्जा सी #/CLR में कोई मतलब नहीं है कर रहे हैं के बाद से यह ref की आवश्यकता होगी/outफ़ील्ड आंतरिक रूप से। साथ ही, ध्यान दें कि मैं इन दोनों खोजशब्दों को जोड़ता हूं क्योंकि वे प्रभावी रूप से समान हैं।

यदि आप अपने ब्लॉग पर Eric Lippert discussed this design point in detail एक पूर्ण स्पष्टीकरण चाहते हैं। (विशेष रूप से निचले भाग के पास पैराग्राफ देखें।)

1

out और ref पैरामीटर के बीच फर्क सिर्फ इतना है कि एक out पैरामीटर एक [out] टोकन यह करने के लिए लागू होगा। जहां तक ​​सीएलआर का संबंध है, वे वही बात हैं।

इसे लागू करने के लिए, कंपाइलर को refफ़ील्ड्स उत्पन्न करना होगा, जो समर्थित नहीं हैं।

यदि आप इसके बारे में सोचते हैं, तो आपको पता चलेगा कि अज्ञात विधि को out पैरामीटर का उपयोग करने की अनुमति देने का कोई मतलब नहीं है।

निम्नलिखित कोड क्या होगा?

static Func<object, object> Mess(out object param) { 
    param = "Original"; 
    return i => param = i; 
} 
static Func<object, object> MessCaller() { 
    object local; 
    return Mess(out local); 
} 
static vouid Main() { 
    Console.WriteLine(MessCaller()("New")); 
    //The local variable that the lambda expression writes to doesn't exist anymore. 
} 
+1

'आउटएट्रिब्यूट 'विशेषता सी # में' आउट 'पैरामीटर पर लागू नहीं है। 'आउटएट्रिब्यूट' एक कस्टम विशेषता है जिसे मार्शलिंग सामान माना जाता है। 'आउट' पैरामीटर को अन्य मेटाडेटा टोकन (' आईएल में '[आउट] द्वारा एनोटेट किया गया है)। आप सी # कोड में 'आउट' के रूप में घोषित 'पैरामीटरइन्फो' के गुणों की पूछताछ करके इस तथ्य को सत्यापित कर सकते हैं। वहां कोई '[आउटएट्रिब्यूट] नहीं है। –

+0

फिक्स्ड; धन्यवाद। – SLaks

1

कुछ त्रुटि प्रबंधन कोड विकसित करते समय मैं इस conundrum में आया था। मैं एक त्रुटि संदेश को एक संदर्भ (आउट) पास करना चाहता था जो लॉग हो जाएगा। इसने मेरे अज्ञात तरीकों को एकाधिक चेक करने का मौका दिया, प्रत्येक त्रुटि संदेश को आवश्यकतानुसार सेट करता है।

मैंने अज्ञात विधि के लिए एक नया रैपर लिखना समाप्त कर दिया जो अलग-अलग काम करता था।लेकिन मैंने जो सोचा था वह किसी के लिए कुछ मूल्य हो सकता है, यह है कि मैं केवल एक निजी विधि बना सकता था जिसमें आउट पैरामीटर था, और एक प्रतिनिधि को परिभाषित किया गया था, और मेरा कोड इसका उपयोग करता था। उम्मीद है कि यह किसी को मदद/प्रेरित करता है।

protected delegate void OutStringDelegate(int divider, out string errorText); 
    protected void codeWrapper(int divider, OutStringDelegate del) 
    { 
     string ErrorMessage = "An Error Occurred."; 

     try 
     { 
      del(divider, out ErrorMessage); 
     } 
     catch 
     { 
      LogError(ErrorMessage); 
     } 
    } 
    public void UseWrapper(int input) 
    { 
     codeWrapper(input, codeToCall); 
    } 
    private int somePrivateValue = 0; 
    private void codeToCall(int divider, out string errorMessage) 
    { 
     errorMessage = "Nice Error Message here!"; 
     somePrivateValue = 1/divider; // call me with zero to cause error. 
    } 
    private void LogError(string msg) 
    { 
     Console.WriteLine(msg); 
    } 
संबंधित मुद्दे