विस्तार विधि और गतिशील वस्तु


96

मैं निम्नलिखित कोड स्निपेट में अपनी समस्या का सारांश देने जा रहा हूं।

List<int> list = new List<int>() { 5, 56, 2, 4, 63, 2 };
Console.WriteLine(list.First());

ऊपर कोड ठीक काम कर रहा है।

अब मैंने निम्नलिखित प्रयास किया

dynamic dList = list;
 Console.WriteLine(dList.First());

लेकिन मुझे RuntimeBinderException मिल रही है। ऐसा क्यों है?


ऐसा लगता है कि इस सवाल का एक डुप्लिकेट सिर्फ 4 दिन पहले पूछा गया stackoverflow.com/questions/5270782/…
jbtule

@jbtule अंतर यह है कि thisयहाँ गतिशील है, लेकिन अगर आप यहाँ उतरते हैं, तो आपको शायद उस प्रश्न को भी देखना चाहिए
nik.shornikov

जवाबों:


131

Stecya के उत्तर पर विस्तार करने के लिए ... विस्तार विधियों को विस्तार विधियों के रूप में डायनेमिक टाइपिंग द्वारा समर्थित नहीं किया जाता है, जैसे कि वे उदाहरण के तरीके थे। हालांकि, यह काम करेगा:

dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));

बेशक, यह उपयोगी हो भी सकता है और नहीं भी। यदि आप डायनामिक टाइपिंग का उपयोग क्यों और कैसे कर रहे हैं, इसके बारे में अधिक जानकारी दे सकते हैं, तो हम और अधिक मदद करने में सक्षम हो सकते हैं।


मैं डायनेमिक ऑब्जेक्ट के साथ खेल रहा था और मुझे यह अपवाद मिला। क्या आपने इस विषय पर कोई लेख लिखा है, जहाँ डायनामिक ऑब्जेक्ट का उपयोग या उपयोग नहीं करना है
santosh singh

19
@geek: व्यक्तिगत रूप से मेरे अंगूठे का नियम केवल उस जगह का उपयोग करना है, dynamicजहां आपको वास्तव में जरूरत है ... मूल रूप से यदि आप अन्यथा सदस्यों को प्रतिबिंब के साथ एक्सेस कर रहे हैं, तो यह एक बड़ा संकेत है। दूसरी ओर, मैं एक डाई-हार्ड स्टैटिक टाइपर हूं - अन्य लोग कम निराशावादी नीतियों का सुझाव दे सकते हैं :)
जॉन स्कीट

2
यह जानने के लिए वापस टाइप करने के लिए अधिक पठनीय हो सकता है, यह काम करता है: Console.WriteLine (((सूची <int>) dList) .First (); या Console.WriteLine ((सूची के रूप में सूची <int>)। पहला ()) ;;
एवी

138

जॉन के जवाब पर विस्तार करने के लिए, यह कारण काम नहीं करता है क्योंकि नियमित, गैर-गतिशील कोड विस्तार विधियाँ उन सभी वर्गों की पूरी खोज करके काम करती हैं जो एक स्थिर वर्ग के लिए संकलक के लिए जानी जाती हैं जिसमें एक विस्तार विधि होती है जो मेल खाती है। खोज नेमस्पेस नामकरण और usingप्रत्येक नामस्थान में उपलब्ध निर्देशों के आधार पर क्रम में जाती है।

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


स्पष्टीकरण के लिए बहुत-बहुत धन्यवाद।
संतोश सिंह

3
क्या ऐसा फीचर ऑफिंग में है? यह निश्चित रूप से एक ब्रेकिंग परिवर्तन होगा; वर्तमान में RunTimeBinderException को फेंकने वाले कॉल अचानक स्रोत पर काम करना शुरू कर देंगे। इसके अलावा, क्या इस तरह की सुविधा को लागू करने के साथ कोई सुरक्षा जोखिम जुड़ा होगा?
ऐनी

5
@ वाणी: क्या हम उस सुविधा को लागू करने की योजना बना रहे हैं? नहीं। क्या कोई सुरक्षा जोखिम हैं? मुझे किसी की जानकारी नहीं है; आपके मन में किस तरह का सुरक्षा जोखिम है? यह कहकर शुरू करें कि कौन हमलावर है और उपयोगकर्ता के लिए वे कौन से खतरे हैं।
एरिक लिपर्ट

@ EricLippert, मैं समझ चुका हूं कि सभी dynamicऑब्जेक्ट C # के बराबर हैं DynamicObject, इसलिए उन्हें अंतर करने का कोई तरीका नहीं है और इसका एक कारण है कि एक्सटेंशन विधियों को जोड़ना संभव नहीं है dynamic, यह सही है?
टॉम सार्डु

@ EricLippert ने इस उत्तर को थोड़ा और विस्तार दिया और "जब कोई भी पैरामीटर गतिशील हो, तो रन-टाइम तक सभी प्रस्तावों को स्थगित कर दिया जाता है " की तर्ज पर वाक्य जोड़ने पर विचार करें । हालांकि यह आपके लिए स्पष्ट है कि यह महत्वपूर्ण बिट SO पर कहीं और मिलना मुश्किल है ( उदाहरण के लिए stackoverflow.com/questions/48324768 देखें )
अलेक्सई लेवेनकोव

18

क्योंकि First()की एक विधि नहीं है List। यह Linq एक्सटेंशन में परिभाषित किया गया हैIEnumerable<>

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.