प्रस्तावना: यदि आप पूर्ण स्पष्टीकरण चाहते हैं तो संपादन पर जाएं। स्पोइलर: विस्तार के तरीके एक कंपाइलर चाल हैं, और वास्तव में एक और तर्क है जब आप उन्हें कहते हैं।
यह विधि समूह के समाधान में है। स्पष्ट रूप से सी # कंपाइलर यह पता लगाने में समय नहीं लगाता है कि आप जिस विधि का उपयोग कर रहे हैं वह अधिभारित है या नहीं; यह हमेशा एक स्पष्ट कलाकार की आवश्यकता है। देखें:
What is a method group in C#?
Method Inference does not work with method group
विधि समूह है कि reader.GetDoubleOrNull
से वापस आता है जो आपके लिए यह कास्ट करने के लिए कोशिश से संकुचित है: GetDoubleOrNull
कि नाम के साथ अतिभारित तरीकों के किसी भी संख्या का उल्लेख कर सकते हैं। आपको इसे स्पष्ट रूप से डालना होगा।
दिलचस्प है, तुम भी एक विधि समूह एक परोक्ष टाइप चर के लिए एक ही कारण के लिए असाइन नहीं कर सकते:
var x = reader.GetDoubleOrNull;
संकलित करने के लिए है, क्योंकि यह एक स्पष्ट कलाकारों की आवश्यकता है विफल रहता है। निम्न परीक्षण वर्ग बाहर
चेक:
संपादित मैं यकीन है कि भ्रम की स्थिति यहाँ विस्तार के तरीकों के साथ क्या करना है कर रहा हूँ
public static class Extensions
{
public static List<T> GetList<T>(this IDataReader reader, Func<string, T> del)
{
throw new NotImplementedException();
}
public static double? GetDoubleOrNull(this IDataReader reader, string columnName)
{
throw new NotImplementedException();
}
public static double? blah(this string s)
{
throw new NotImplementedException();
}
}
आप सफलतापूर्वक कॉल कर सकते हैं
var x = reader.GetList(Extensions.blah);
यह क्यों हो सकता है? blah
एक स्थिर विस्तार विधि भी है, इसलिए, आपके सबूतों के आधार पर, ऐसा लगता है कि उपर्युक्त रेखा संकलित नहीं होनी चाहिए। इसके अलावा बातें उलझी, चलो इस विधि जोड़ें:
public static List<T> GetList2<T>(this IDataReader reader, Func<IDataReader, string, T> del)
{
throw new NotImplementedException();
}
अब आप
x = reader.GetList2(Extensions.GetDoubleOrNull);
कॉल कर सकते हैं और इसे ठीक से संकलित कर देगा। क्या देता है?
यहां जवाब है: एक्सटेंशन विधि वास्तव में आपकी ऑब्जेक्ट्स में विधियां जोड़ें। वे वास्तव में एक कंपाइलर चाल हैं जो आपको प्रोग्राम करने की अनुमति देने के लिए हैं जैसे कि वे विधियां आपकी कक्षाओं का हिस्सा थीं। here से:
अपने कोड में आप उदाहरण विधि वाक्य रचना के साथ विस्तार विधि आह्वान। हालांकि, कंपाइलर द्वारा उत्पन्न इंटरमीडिएट भाषा (आईएल) स्थिर कोड पर आपके कोड को कॉल में अनुवादित करती है। इसलिए, encapsulation का सिद्धांत वास्तव में उल्लंघन नहीं किया जा रहा है। वास्तव में, विस्तार विधियां निजी चर तक पहुंचने वाले प्रकार में नहीं पहुंच सकती हैं।
इसलिए, जब आप फोन
var x = reader.GetDoubleOrNull("myColumnName");
है क्या वास्तव में संकलित और निष्पादित किया जा रहा अनिवार्य रूप से यह है (एक पूरी तरह से वैध कॉल, भले ही यह एक विस्तार विधि है):
var x = Extensions.GetDoubleOrNull(reader, "myColumnName");
तो , जब आप GetDoubleOrNull
को Func<string, double?>
के लिए तर्क के रूप में उपयोग करने का प्रयास करते हैं, तो संकलक जा रहा है "मैं GetDoubleOrNull
को Func<IDataReader, string, double?>
में बदल सकता हूं क्योंकि इसमें दो तर्क हैं, लेकिन मैं नहीं करता है सिर्फ दो आर्ग कि सी # के साथ एक स्थिर विधि यह: अब कैसे एक Func<string, double?>
"
में बारी करने भले ही आप यह कॉल कर रहे हैं जैसे कि वह एक आर्ग के साथ IDataReader
का एक उदाहरण विधि है, यह नहीं है कंपाइलर ने आपको सोचने में धोखा दिया है IDataReader
का हिस्सा है।
बहुत रोचक। एक स्पष्ट कास्ट '' var x = reader.GetList ((Func) पाठक।GetDoubleOrNull) '' भी काम करता है। Resharper कास्ट अनावश्यक के रूप में चिह्नित करता है, लेकिन इसके बिना संकलन विफल रहता है। क्या जॉन स्कीट चारों ओर है? –
क्या जॉन स्कीट (या शायद एरिक लिपर्ट) का आह्वान करने का कोई तरीका है? उनका नाम तीन बार या कुछ कहें? – Chris
संबंधित: http://stackoverflow.com/questions/7745852/method-inference-does-not-work-with-method-group और http://stackoverflow.com/questions/2057146/compiler-ambiguous-invocation-error -नानाम-विधि-और-विधि-समूह-मजेदार – AakashM