2012-03-07 23 views
13

साथ एक प्रतिनिधि के लिए एक विस्तार विधि समूह परिवर्तित मैं निम्नलिखित हस्ताक्षरों के साथ IDataReader पर दो विस्तार तरीकों:एक सामान्य प्रकार

internal static List<T> GetList<T>(this IDataReader reader, Func<string, T> del) 

internal static double? GetDoubleOrNull(this IDataReader reader, string columnName) 

GetDoubleOrNull किसी भी भार के पास नहीं है।

कहीं और, मैं

Func<string, double?> del = reader.GetDoubleOrNull; 

var x = reader.GetList(del); 

या

var x = reader.GetList<double?>(reader.GetDoubleOrNull); 

करने के लिए या सिर्फ तरह

public double? blah(string s) 

var x = reader.GetList(blah); 

एक उदाहरण विधि में पारित कर सकती हूं लेकिन मैं

ऐसा नहीं कर सकते
var x = reader.GetList(reader.GetDoubleOrNull); 

संकलक त्रुटि

cannot convert from 'method group' to 'System.Func<string,double?>' 

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

वास्तव में भ्रमित करने वाला हिस्सा यह है कि blah में गुजरते समय यह कैसा लगता है।

+3

बहुत रोचक। एक स्पष्ट कास्ट '' var x = reader.GetList ((Func ) पाठक।GetDoubleOrNull) '' भी काम करता है। Resharper कास्ट अनावश्यक के रूप में चिह्नित करता है, लेकिन इसके बिना संकलन विफल रहता है। क्या जॉन स्कीट चारों ओर है? –

+3

क्या जॉन स्कीट (या शायद एरिक लिपर्ट) का आह्वान करने का कोई तरीका है? उनका नाम तीन बार या कुछ कहें? – Chris

+1

संबंधित: http://stackoverflow.com/questions/7745852/method-inference-does-not-work-with-method-group और http://stackoverflow.com/questions/2057146/compiler-ambiguous-invocation-error -नानाम-विधि-और-विधि-समूह-मजेदार – AakashM

उत्तर

0

GetDoubleOrNull एक डबल लौटाता है? GetList एक IDataReader और एक System.Func<string,int?>

त्रुटि संदेश उम्मीद एक बालक

सार्वजनिक डबल भ्रामक है? ब्लाह (स्ट्रिंग एस)

var x = reader.GetList (blah);

ब्लहा इस कॉल में एक प्रतिनिधि है। GetList (GetDoubleOrNull) में यह DoubleOrNull पाने का नतीजा है।

हालांकि अच्छा सवाल है। जवाब पोस्ट करें जो मैंने मदद की है या नहीं।

+0

'int'' एक टाइपो होना चाहिए, इसे 'डबल' में बदलना अभी भी कंपाइलर त्रुटि देता है। –

+0

जेसेक सही है। मेरी गलती। माफ़ कीजिये। – Moss

+1

आपने कहा "गेटलिस्ट (GetDoubleOrNull) में यह DoubleOrNull पाने का नतीजा है" लेकिन यह सही नहीं है। इस मामले में 'GetDoubleOrNull' का मूल्यांकन नहीं किया जा रहा है, इसे विधि समूह के रूप में माना जा रहा है। – Chris

8

प्रस्तावना: यदि आप पूर्ण स्पष्टीकरण चाहते हैं तो संपादन पर जाएं। स्पोइलर: विस्तार के तरीके एक कंपाइलर चाल हैं, और वास्तव में एक और तर्क है जब आप उन्हें कहते हैं।

यह विधि समूह के समाधान में है। स्पष्ट रूप से सी # कंपाइलर यह पता लगाने में समय नहीं लगाता है कि आप जिस विधि का उपयोग कर रहे हैं वह अधिभारित है या नहीं; यह हमेशा एक स्पष्ट कलाकार की आवश्यकता है। देखें:

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 का हिस्सा है।

+0

उत्कृष्ट उत्तर और शोध। मैं इसे फिर से +1 करना चाहता हूं। ;-) – Chris

+3

मैं जॉन स्कीट नहीं हूं, लेकिन मैं जो कर सकता हूं वह कर सकता हूं: डी – eouw0o83hf

+0

आपके उत्तर के लिए धन्यवाद। दुर्भाग्यवश अभी भी मुझे इस मुद्दे को स्पष्ट रूप से समझ में नहीं आता है। आपके द्वारा संदर्भित पहला प्रश्न वह है जिसे मैं जानता हूं। मैंने दूसरा, साथ ही आकाशम द्वारा पोस्ट किए गए लोगों को भी पढ़ा, और यह मुझे लगता है कि यह कैसे आता है कि ओवरलोड रिज़ॉल्यूशन कैसे रिटर्न प्रकार को खाते में नहीं लेता है। मैं समझता हूँ कि। लेकिन फिर, 'ब्लाह' काम में कैसे गुजरता है? क्या उस मामले में कोई ओवरलोड रिज़ॉल्यूशन नहीं होता है? यदि नहीं, तो क्यों नहीं? यदि हां, तो यह कैसे सफल होता है? – Moss

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