2017-01-22 29 views
9

इस कोड संकलन नहीं होगा:अस्पष्ट विस्तार विधि कॉल

using System; 
using System.Runtime.CompilerServices; 

static class Extensions { 
    public static void Foo(this A a, Exception e = null, string memberName = "") { 
    } 

    public static void Foo<T>(this A a, T t, Exception e = null, string memberName = "") 
     where T : class, IB { 
    } 
} 

interface IB { } 

class A { } 

class Program { 
    public static void Main() { 
     var a = new A(); 
     var e = new Exception(); 

     a.Foo(e); //<- Compile error "ambiguous call" 
    } 
} 

लेकिन अगर मैं पिछले string तर्क को नष्ट सब कुछ ठीक है:

public static void Foo(this A a, Exception e = null) { 
    } 

    public static void Foo<T>(this A a, T t, Exception e = null) 
     where T : class, IB { 
    } 

प्रश्न है - कि ये वैकल्पिक क्यों string तर्कों को तोड़ने संकलक की पसंद विधि कॉल का?

जोड़ा गया: स्पष्ट प्रश्न: मैं क्यों संकलक पहले मामले में सही अधिभार नहीं चुन सकते हैं मिलता है न, लेकिन दूसरा एक में यह कर सकता है?

संपादित: [CallerMemberName] विशेषता यहाँ तो मैं सवाल से उसे हटा दिया है एक समस्या का एक कारण नहीं है।

+1

बस स्पष्ट करने के लिए: निकाला जा रहा है '[CallerMemberName]' अकेले विशेषता * कोई * प्रभाव पड़ता है, संकलक एक त्रुटि आउटपुट। पूरे तर्क को हटाकर '[कॉलरमेनम्बर] स्ट्रिंग सदस्यनाम =" "* * * एक प्रभाव है, कोड संकलित करता है। मैं यही देखता हूं। सही? –

+4

** सी # विशिष्टता: 7.5.3.2 बेहतर कार्य सदस्य: ** * अन्यथा यदि एमपी के सभी मानकों में एक समान तर्क है जबकि एमक्यू में कम से कम एक वैकल्पिक पैरामीटर के लिए डिफ़ॉल्ट तर्कों को प्रतिस्थापित करने की आवश्यकता है तो एमपी एमक्यू से बेहतर है। * वह नियम दूसरे मामले में लागू होता है, लेकिन पहले मामले में लागू नहीं किया जा सकता है। – PetSerAl

+0

यदि आप केवल '[कॉलरमेम्बरनाम]' विशेषता को हटाते हैं, लेकिन पैरामीटर 'स्ट्रिंग सदस्यनाम = "" 'दोनों विधियों में रखें, तो क्या होता है? संपादित करें: @OndrejTucny पहले से ही कहा है कि, मैं पोस्ट करने के बाद देखते हैं। अभी भी एक अच्छा सवाल है। –

उत्तर

6

@PetSerAl पहले से ही टिप्पणी में कल्पना की ओर इशारा किया, लेकिन मुझे लगता है कि सादे से अंग्रेज़ी में अनुवाद करते हैं:

सी # भाषा एक नियम का कहना है कि छोड़े गए डिफॉल्ट की बहस के बिना एक अधिभार के साथ छोड़े गए चूक एक अधिभार से अधिक पसंद किया जाता है तर्क। यह नियम Foo(this A a, Exception e = null)Foo(this A a, T t, Exception e = null) से बेहतर मिलान बनाता है।

सी # भाषा एक नियम कह रही है कि एक छोड़े गए डिफॉल्ट तर्क के साथ एक अधिभार दो छोड़े गए डिफॉल्ट तर्क के साथ एक अधिभार से अधिक पसंद किया जाता है नहीं है। क्योंकि इसमें ऐसा नियम नहीं है, Foo(this A a, Exception e = null, string s = "")Foo<T>(this A a, T t, Exception e = null, string s = "") से अधिक पसंद नहीं है।

इस समस्या से बचने के लिए सामान्य रूप से अतिरिक्त भार के उपलब्ध कराने के बजाय डिफ़ॉल्ट पैरामीटर मान का उपयोग करके किया जाएगा सबसे आसान तरीका है। आप CallerMemberName के लिए पैरामीटर सामान्य मानों काम करने की जरूरत है, लेकिन आप अतिरिक्त भार के कि Exception छोड़ देते हैं प्रदान कर सकते हैं, और उस के लिए null पास करके वास्तविक कार्यान्वयन के लिए आगे।

नोट: यह सुनिश्चित करना कि Foo<T>(this A a, T t, string s = "") को तब तक नहीं चुना जाता है जब Foo(this A a, Exception e, string s = "") उपलब्ध है, तो यह एक मुश्किल समस्या होगी। यदि आपका चर स्थिर रूप से Exception के रूप में टाइप किया गया है, तो गैर-जेनेरिक विधि को प्राथमिकता दी जाएगी, लेकिन यदि यह स्थिर रूप से टाइप किया गया है उदा। ArgumentException, तो T=ArgumentException आधार वर्ग Exception तुलना में एक बेहतर मैच है, और T=ArgumentException में त्रुटि विधि आप कॉल करना चाहते लेने के लिए बहुत देर हो चुकी पता लगाया जाएगा। शायद यह सबसे सुरक्षित होगाException के बाद Tजगह, और हमेशा की आवश्यकता होती है एक अपवाद (संभवतः null) जब सामान्य विधि का इरादा है में पारित किया जा रहा।

+1

ग्रेट उत्तर। क्या इसका मतलब यह है कि जब ओवरलोड रिज़ॉल्यूशन की बात आती है तो 'टी: क्लास, आईबी' को बाध्यकारी द्वारा पूरी तरह नजरअंदाज कर दिया जाता है? – Szer

+2

@Szer हाँ, [सामान्य की कमी के लिए एक विधि के हस्ताक्षर का हिस्सा नहीं हैं।] (@ Szer हाँ, सामान्य [कमी नहीं एक तरीकों हस्ताक्षर का हिस्सा हैं।] (Https://blogs.msdn.microsoft.com/ericlippert/2009/12/10/कमी-हैं-न-भाग ऑफ द हस्ताक्षर /) – InBetween

+0

यहाँ सी # भाषा विशिष्टता से सटीक उद्धरण है: _ • \t अन्यथा यदि सांसद के सभी मापदंडों एक इसी तर्क है डिफ़ॉल्ट तर्क करने की जरूरत है, जबकि एमक्यू में कम से कम एक वैकल्पिक पैरामीटर के लिए प्रतिस्थापित किया जाए तो MP MQ._ –

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