2012-11-13 35 views
12

.NET 4 का उपयोग करके, मैं नीचे दिए गए नमूने में पहली विधि कॉल को हल करने के लिए कंपाइलर की अक्षमता से उलझन में हूं।डिफ़ॉल्ट पैरामीटर और जेनेरिक के साथ विधि समाधान समस्या

using System; 

namespace MethodResolutionTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      NonGeneric foo = null; 

      // ambiguous 
      foo.Ext1(x => new NonGeneric()); 

      // resolves to first Ext1 
      foo.Ext1(x => new NonGeneric(), 1); 


      // resolves to first Ext2 
      foo.Ext2(x => new NonGeneric()); 

      // resolves to first Ext2 
      foo.Ext2(x => new NonGeneric(), 1); 

      // resolves to second Ext2 
      foo.Ext2(x => "foo"); 

      // resolves to second Ext2 
      foo.Ext2(x => "foo", 1); 


      // resolves to first Ext3 
      foo.Ext3(x => new NonGeneric()); 

      // resolves to first Ext3 
      foo.Ext3(x => new NonGeneric(), 1); 

      // resolves to second Ext3 
      foo.Ext3(x => "foo"); 

      // resolves to second Ext3 
      foo.Ext3(x => "foo", 1); 
     } 
    } 

    public class NonGeneric 
    { 
    } 

    public class Generic<T> : NonGeneric 
    { 
    } 

    public static class Extensions1 
    { 
     public static NonGeneric Ext1(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext, int i = 0) 
     { 
      return null; 
     } 

     public static Generic<TNext> Ext1<TNext>(this NonGeneric first, Func<NonGeneric, TNext> getNext, int i = 0, string s = null) 
     { 
      return null; 
     } 
    } 

    // only difference between Extensions2 and Extensions1 is that the second overload no longer has a default string parameter 
    public static class Extensions2 
    { 
     public static NonGeneric Ext2(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext, int i = 0) 
     { 
      return null; 
     } 

     public static Generic<TNext> Ext2<TNext>(this NonGeneric first, Func<NonGeneric, TNext> getNext, int i = 0) 
     { 
      return null; 
     } 
    } 

    // Extensions3 explicitly defines an overload that does not default the int parameter 
    public static class Extensions3 
    { 
     public static NonGeneric Ext3(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext) 
     { 
      return Ext3(first, getNext, default(int)); 
     } 

     public static NonGeneric Ext3(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext, int i = 0) 
     { 
      return null; 
     } 

     public static Generic<TNext> Ext3<TNext>(this NonGeneric first, Func<NonGeneric, TNext> getNext, int i = 0) 
     { 
      return null; 
     } 
    } 
} 

क्या कोई इस पर कुछ प्रकाश डाल सकता है? मुझे संदेह है कि मेरे पास वास्तव में कंपाइलर (Extensions3 के अनुसार) की मदद करने के लिए मेरे एपीआई को संशोधित करने के अलावा अन्य कोई रास्ता नहीं है, लेकिन यदि कोई आसान/बेहतर तरीका है तो मुझे यह सुनना अच्छा लगेगा।

उत्तर

1

यह संदिग्ध है क्योंकि आपके पास दूसरे Ext1 एक्सटेंशन विधि में दो वैकल्पिक पैरामीटर हैं। चूंकि दोनों पैरामीटर पहले कॉल में छोड़े जाते हैं, इसलिए संकलक यह नहीं जानता कि आप किस का उपयोग करना चाहते हैं।

C# 4.0 Language Specification से:

§7.5.3 अधिभार संकल्प:

लागू उम्मीदवार समारोह के सदस्यों के सेट को देखते हुए लगता है कि सेट में सबसे अच्छा समारोह सदस्य स्थित है। यदि सेट में केवल एक फ़ंक्शन सदस्य होता है, तो वह फ़ंक्शन सदस्य सबसे अच्छा फ़ंक्शन सदस्य होता है। अन्यथा, सबसे अच्छा फ़ंक्शन सदस्य एक फ़ंक्शन सदस्य होता है जो दिए गए तर्क सूची के संबंध में अन्य सभी फ़ंक्शन सदस्यों से बेहतर होता है, बशर्ते कि प्रत्येक फ़ंक्शन सदस्य की तुलना अन्य सभी फ़ंक्शन सदस्यों से §7.5.3.2 में नियमों का उपयोग करके की जाती है। यदि कोई अन्य फ़ंक्शन सदस्य नहीं है जो अन्य सभी फ़ंक्शन सदस्यों से बेहतर है, तो फ़ंक्शन सदस्य आमंत्रण संदिग्ध है और बाध्यकारी-समय त्रुटि होती है।

इसके अलावा, तहत §7.5.3.2 बेहतर समारोह सदस्य:

कोई संगत तर्क के साथ वैकल्पिक पैरामीटर पैरामीटर सूची

से निकाल दिए जाते क्या इसका मतलब यह है कि जब आप विधि कॉल में दो अंतिम तर्कों को छोड़ दें और NonGeneric प्रकार अनुमानित है (§7.5.2 के तहत प्रकार अनुमान के बारे में पढ़ें), दोनों विधियां इस तरह दिखेगी:

Ext1(this NonGeneric first, Func<NonGeneric, NonGeneric> getNext) 

इस प्रकार, वे अस्पष्ट होगा ...

मैं §7.5.3.2 या यहां तक ​​कि अधिक जानकारी के लिए विनिर्देश की पूरी §7.5.3 पढ़ने की सिफारिश करेंगे।

समाधान या तो अपने विधि घोषणाओं को बदलने के लिए या पहले अधिभार पूरी तरह निकाल दें और जाने दूसरा काम :)

+0

संकलक दोनों 'Extensions2' और' Extensions3' स्थितियों में ठीक चुनता है, इसलिए यह नहीं है है यह सरल है। साथ ही, अगर मैं डिफ़ॉल्ट 'int' पैरामीटर नहीं चाहता था, तो जाहिर है कि मैंने इसे पहले स्थान पर घोषित नहीं किया होगा! –

+0

लेकिन वैकल्पिक पैरामीटर के साथ आपके पास दो विधियां क्यों हैं जो वैकल्पिक पैरामीटर छोड़े जाने पर प्रभावी रूप से अस्पष्ट हैं? यदि आपको बिल्कुल ** ** दोनों विधियों की आवश्यकता है, तो आपको या तो अपने 'एक्सटेंशन 2' या 'एक्सटेंशन 3' समाधानों का उपयोग करना होगा। – khellang

+0

@ खेलेंग: क्या आप ऐसे व्यवहार (ओवरलोड रिज़ॉल्यूशन अस्पष्टता) की ओर अग्रसर सी # भाषा विनिर्देश खंडों को इंगित कर सकते हैं? –