2010-05-18 32 views
6

मैं सिर्फ एक स्थिति मारा जहां एक विधि प्रेषण अस्पष्ट था और सोचा कि अगर किसी को भी किस आधार संकलक पर समझा सकता है (.NET 4.0.30319) क्याC# जेनेरिक अतिभारित विधि भेजने अस्पष्ट

interface IfaceA 
{ 

} 

interface IfaceB<T> 
{ 
    void Add(IfaceA a); 
    T Add(T t); 
} 

class ConcreteA : IfaceA 
{ 

} 

class abstract BaseClassB<T> : IfaceB<T> 
{ 
    public virtual T Add(T t) { ... } 
    public virtual void Add(IfaceA a) { ... } 
} 

class ConcreteB : BaseClassB<IfaceA> 
{ 
    // does not override one of the relevant methods 
} 

void code() 
{ 
    var concreteB = new ConcreteB(); 

    // it will call void Add(IfaceA a) 
    concreteB.Add(new ConcreteA()); 
} 

कॉल करने के लिए ओवरलोड चुनता है किसी भी मामले में, संकलक मुझे चेतावनी क्यों नहीं देता है या यह संकलित क्यों करता है? किसी भी उत्तर के लिए आपको बहुत बहुत धन्यवाद।

+0

यदि आप कॉल से वापसी मूल्य की अपेक्षा करते हैं तो क्या होता है, यानी 'var result = concreteB.Add (new ConcreteA()); '? –

+1

अपनी जेनेरिक विधि को एक "वापसी टी" वापस लेना है और दूसरा एक "शून्य" प्रकार है। कंपाइलर उनके बीच अंतर कर सकता है। – KroaX

+0

संकलक शिकायत करेगा कि 'var' का उपयोग नहीं किया जा सकता है, क्योंकि वह निहित रूप से टाइप किए गए चर – Sebastian

उत्तर

2

यह C# 4 specification की धारा 7.5.3.2 में नियमों का पालन करती ("बेटर समारोह सदस्य") द्वारा अपनी पसंद के लिए मजबूर कर सकते हैं।

पहला (ठीक है, यह देखने के बाद कि दोनों विधियां लागू) हमें तर्क प्रकारों से पैरामीटर प्रकारों में रूपांतरणों की जांच करने की आवश्यकता है। इस मामले में यह काफी सरल है क्योंकि केवल एक तर्क है। तर्क प्रकार के पैरामीटर प्रकार में रूपांतरण का कोई भी रूपांतरण "बेहतर" नहीं है क्योंकि दोनों ConcreteA से IfaceA में परिवर्तित हो रहे हैं। इसलिए यह मापदंड के अगले सेट, इस सहित पर जाता है:

अन्यथा, यदि सांसद MQ की तुलना में अधिक विशिष्ट पैरामीटर प्रकार है, तो सांसद MQ से बेहतर है। चलो {आर 1, आर 2, ..., आरएन} और {एस 1, एस 2, ..., एसएन} अप्रतिबंधित और अप्रत्याशित पैरामीटर प्रकार एमपी और एमक्यू का प्रतिनिधित्व करते हैं। SX से विशिष्ट: सांसद की पैरामीटर प्रकार से MQ के अधिक विशिष्ट हैं, प्रत्येक पैरामीटर के लिए, RX नहीं कम SX से विशिष्ट है, और, कम से कम एक पैरामीटर के लिए, RX SX की तुलना में अधिक विशिष्ट है

  • एक प्रकार पैरामीटर गैर-प्रकार पैरामीटर से कम विशिष्ट है।
  • ...

तो भले ही रूपांतरण समान रूप से अच्छा है, IfaceA सीधे (बल्कि प्रतिनिधियों के माध्यम से की तुलना में) का उपयोग कर अधिभार समझा जाता है "बेहतर" क्योंकि प्रकार का एक पैरामीटर IfaceA अधिक विशिष्ट है T प्रकार के पैरामीटर से।

इस व्यवहार पर चेतावनी देने के लिए कंपाइलर प्राप्त करने का कोई तरीका नहीं है - यह केवल सामान्य अधिभार समाधान है।

+0

ठीक है एक लाख धन्यवाद। मुझे लगता है कि इसका मतलब है कि मैं उस विनिर्देश को पढ़ूंगा। मैं सिर्फ जावा कन्वर्ट हूं और इस परियोजना के लिए सी # का उपयोग करना है। हालांकि वास्तव में मुझे लगता है कि यह अधिक उपयोगी है, लेकिन मुझे लगता है कि किसी भी सुविधा में कुछ किनारे के मामलों को भी जोड़ता है ... – Sebastian

1

क्योंकि संकलक सबसे विशिष्ट पहले चुनता है।

यदि आप ऐसा तरह फोन क्या होता है:

void code() 
{ 
    var concreteB = new ConcreteB(); 

    IfaceA x = concreteB.Add(new ConcreteA()); 
} 
+0

को शून्य निर्दिष्ट नहीं कर सकता है, लेकिन' शून्य जोड़ें (ifaceA a) 'और अधिक विशिष्ट क्यों होगा? क्या ऐसा इसलिए है क्योंकि मैं लौटा परिणाम का उपयोग नहीं करता?और इसके अलावा, क्या आप जानते हैं कि क्या मुझे एक चेतावनी देने के लिए एक कंपाइलर विकल्प है? – Sebastian

+0

@sebgod: आप संकलक चेतावनी जारी करने के लिए '# चेतावनी 'निर्देश का उपयोग कर सकते हैं। –

+0

यदि मैं 'इफेसए एक्स = कंक्रीट बी। एड (नया कंक्रीटए()) चुनता हूं तो कोड संकलित नहीं होगा;': IFaceA और शून्य – Sebastian

1

यह कुछ हद तक मुझे की याद दिलाता है "प्रकार निष्कर्ष एक-गो-गो" Jon Skeet's BrainTeaser में। आप संकलक पर भरोसा नहीं करना चाहते हैं, तो आप बुला Add<ConcreteA>(new ConcreteA())

+0

मेरे शिक्षक ने हमेशा मुझे क्या बताया, कभी भी अपने कंपाइलर पर विश्वास न करें – Sebastian

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