2010-01-02 9 views
16

स्टैक ओवरव्लो पर कई सी # प्रश्न पूछें कि out या ref पैरामीटर के साथ अज्ञात प्रतिनिधि/लैम्बडा कैसे बनाएं। उदाहरण के लिए देखें,:गुमनाम प्रतिनिधि/lambdas infer प्रकार बाहर/रेफ पैरामीटर पर क्यों नहीं?

ऐसा करने के लिए, आप बस, पैरामीटर के प्रकार निर्दिष्ट करने की आवश्यकता के रूप में:

public void delegate D(out T p); 
// ... 
D a = (out T t) => { ... };  // Lambda syntax. 
D b = delegate(out T t) { ... }; // Anonymous delegate syntax. 

क्या मैं उत्सुक हूं कि इस प्रकार का स्पष्ट रूप से आवश्यकता क्यों है। क्या कोई विशेष कारण है कि यह मामला है? वह है, एक कंपाइलर/भाषा दृष्टिकोण से, निम्नलिखित क्यों अनुमति नहीं है?

D a = (out t) => { ... };  // Lambda syntax -- implicit typing. 
D b = delegate(out t) { ... }; // Anonymous delegate syntax -- implicit typing. 

या और भी बेहतर, बस:

D a = (t) => { ... };  // Lambda syntax -- implicit typing and ref|out-ness. 
D b = delegate(t) { ... }; // Anonymous delegate syntax -- implicit typing and ref|out-ness. 
+3

मैं इस बारे में उत्सुक हूं। आइए उम्मीद करते हैं कि एरिक लिपर्ट इस पोस्ट को नोटिस करते हैं ... वह इस के लिए सार्थक उत्तर देने में सक्षम होने के लिए सबसे ज्यादा पसंद करते हैं। – LBushkin

+2

एलबुशकिन, यदि आप मेरे ध्यान में कुछ लाने के लिए चाहते हैं तो आप हमेशा मेरे ब्लॉग पर संपर्क लिंक के माध्यम से मुझे भेज सकते हैं। –

+0

'प्रतिनिधि' कीवर्ड के साथ अज्ञात विधियों के लिए, नियम यह है कि आप या तो कुछ भी निर्दिष्ट नहीं करते हैं (यहां तक ​​कि ब्रांडेसिस '() 'को छोड़ दें) या पैरामीटर प्रकार और संशोधक जैसे' रेफरी '/' आउट' सहित पूर्ण हस्ताक्षर निर्दिष्ट करें। तो 'ref'/'out' कोई अपवाद नहीं है। लैम्बडास के लिए, आपका विचार समझ में आता है लेकिन मुझे यकीन नहीं है कि मुझे लगता है कि यह एक अच्छा है। वाक्यविन्यास '(आउट टी) => {...} 'यह" आउट "जैसा दिखता है पैरामीटर का प्रकार है। फिर 't => {...} 'बेहतर है, लेकिन यह" खतरनाक "हो सकता है अगर कोई' डी 'का अर्थ भूल गया और' बाहर 'को महसूस किए बिना लैम्ब्डा के शरीर' {...} 'को संपादित किया 'टी' की प्रकृति। –

उत्तर

17

दिलचस्प सवाल है, इसी तरह की है।

सबसे पहले, अनाम विधियों और लैम्ब्डा के बीच अंतर पर विचार करें। कंपाइलर लेखक के परिप्रेक्ष्य से, सबसे महत्वपूर्ण अंतर यह है कि लैम्ब्डा को संकलक को उस लक्ष्य से पैरामीटर के प्रकार का अनुमान लगाने की आवश्यकता हो सकती है, जिस पर लैम्ब्डा को असाइन किया जा रहा है; सी # 2 अज्ञात विधियों में यह सुविधा नहीं है। यह सुविधा एक छोटे से अंतर की तरह प्रतीत होती है लेकिन असल में यह कंपाइलर के कार्यान्वयन पर प्रमुख विध्वंस है। ऐसा क्यों है पर कुछ विचार के लिए इस विषय पर अपने ब्लॉग श्रृंखला देखें:

http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx

तो अब के अपने वास्तविक प्रश्न के आने दो: क्यों हम के मापदंडों को लक्ष्य प्रकार से हक़ीक़त/refness अनुमान नहीं लगा सकता लैम्ब्डा। यही है, अगर हमारे पास प्रतिनिधि शून्य डी (बाहर int x) है तो निश्चित रूप से डी डी = x => {x = 10; } अनुमान लगा सकता है कि एक्स "बाहर int" है।

कोई तकनीकी कारण नहीं है कि मुझे पता है कि हम ऐसा क्यों नहीं कर सके। आंतरिक रूप से कंपाइलर में आउट/रेफ प्रकार किसी अन्य प्रकार के प्रकार के रूप में प्रदर्शित होते हैं।

हालांकि, विशेषताएं केवल इसलिए नहीं की जाती हैं क्योंकि वे किया जा सकता है; वे ऐसा इसलिए करते हैं क्योंकि ऐसा करने के लिए एक अनिवार्य कारण है।लैम्बडास के लिए, पहली जगह टाइप अनुमान लगाने के लिए अनिवार्य कारण LINQ है; हम लैम्बडास के साथ एक विधि कॉल में एक क्वेरी समझ पर एक सरल वाक्य रचनात्मक परिवर्तन करने में सक्षम होना चाहते हैं, और विधि प्रकार अनुमान इंजन सभी लैम्ब्डा पैरामीटर के प्रकारों को बाहर करने दें। उत्पन्न LINQ विधियों में से कोई भी आउट या रेफ पैरामीटर के साथ प्रतिनिधि नहीं है।

तो, हमारे पास सुविधा करने के लिए कोई अनिवार्य कारण नहीं है। प्रतिनिधि जो बाहर/रेफरी पैरामीटर अपेक्षाकृत दुर्लभ हैं। और उन प्रतिनिधियों को भेड़ के बच्चे का असाइनमेंट अभी भी दुर्लभ है। तो यह एक ऐसी सुविधा है जिसकी हमें आवश्यकता नहीं है, और इससे लगभग कोई फायदा नहीं होता है।

सी # 3 विजुअल स्टूडियो शेड्यूल पर "लंबा ध्रुव" था; हमारे पास वीएस में एक घटक जहाज करने वाली किसी भी टीम के नियत कार्य के अधिकांश दिन थे। इसका मतलब था कि हर दिन हमने शेड्यूल फिसल दिया, पूरे डिवीजन फिसल गया। यह अनावश्यक सुविधाओं पर समय बिताने के लिए एक शक्तिशाली असंतोष था जिसने किसी को फायदा नहीं पहुंचाया। तो काम कभी नहीं किया गया था।

मैं मानता हूं कि यहां अधिक संगत होना अच्छा होगा, लेकिन ऐसा होने की संभावना नहीं है। हमारे पास कई उच्च प्राथमिकताएं हैं।

+1

मुझे लगता है कि हर कोई इस बात से अवगत है कि आप कितने व्यस्त हैं, लेकिन यह जानना बेहद अच्छा है कि तकनीकी कारणों से दरवाजा बंद नहीं है, और यह किसी दिन सैद्धांतिक रूप से संभव है। इनपुट के लिए धन्यवाद, एरिक! –

2
Eric Lippert's comment से क्यों घोषणा और एक var चर का काम विभाजित नहीं किया जा सकता है पर

:

मैं मानता हूँ सिद्धांत रूप में यह किया जा सकता है कि , लेकिन यह आपके त्वरित स्केच इंगित करने की तुलना में अभ्यास में बल्कि अधिक जटिल है। var न केवल यह आवश्यक है कि प्रारंभकर्ता हो, यह भी आवश्यक है कि प्रारंभकर्ता चर को संदर्भित न करे। यदि आपके पास int एम (int int) है तो आप "int x = m (ex x) कह सकते हैं;" लेकिन आप "var x = m (ex x) नहीं कह सकते हैं;" क्योंकि एम पर ओवरलोड रिज़ॉल्यूशन करने के लिए, हमें एक्स के प्रकार को जानने की जरूरत है, जिसे हम समझने का प्रयास कर रहे हैं। क्या यह कहना वैध होगा "var s; अगर (बी) एम (आउट एस); अन्य एस = 0;" ?

मैं आपके सवाल का जवाब लगता था, पर विचार उदाहरण के लिए,

D a = (out var x) => x = M(out x); 
+2

मुझे इतना यकीन नहीं है। आप इस तथ्य को कैसे समझाते हैं कि यदि आप 'आउट' कीवर्ड को हटाते हैं तो संकलक अनुमान लगा सकता है? प्रतिनिधि प्रकार 'डी' पूरी तरह से' x' के प्रकार का निर्धारण करना चाहिए। – LBushkin

+1

मुझे विश्वास नहीं है कि यह मामला है। यहां, हम जानते हैं कि हम कुछ ऐसा करने की कोशिश कर रहे हैं जो 'डी' जैसा दिखता है। यदि दाईं ओर का परिणाम मेल नहीं खाता है, तो क्या यह स्पष्ट नहीं होगा? 'Var' उदाहरण के साथ, यह कुछ भी हो सकता है, इसलिए कंपाइलर के पास "सही उत्तर" जैसा दिखना चाहिए इसके बारे में कोई संकेत नहीं है। [ओह! एल बुशकिन ने मुझे पंच पर हरा दिया!] –

संबंधित मुद्दे