2011-02-05 16 views
18

मैं दूसरे दिन यह देखा, कहते हैं कि तुम दो अतिभारित तरीकों:विधि अधिभार संकल्प

public void Print<T>(IEnumerable<T> items) { 
    Console.WriteLine("IEnumerable T"); 
} 
public void Print<T>(T item) { 
    Console.WriteLine("Single T"); 
} 

इस कोड:

public void TestMethod() { 
    var persons = new[] { 
     new Person { Name = "Yan", Age = 28 }, 
     new Person { Name = "Yinan", Age = 28 } 
    }; 
    Print(persons); 
    Print(persons.ToList()); 
} 

प्रिंट:

Single T 
Single T 

Person[] और List<Person>T से बेहतर मिलान क्यों हैं इन मामलों में IEnumerable<T> से वे हैं?

धन्यवाद,

अद्यतन: इसके अलावा, अगर आप एक और अधिभार है

public void Print<T>(List<T> items) { 
    Console.WriteLine("List T"); 
} 

Print(persons.ToList()); वास्तव में List T बजाय Single T प्रिंट होगा।

+2

कॉलिंग 'प्रिंट (व्यक्तियों के रूप में IENumerable );' अन्य विधि को कॉल करना चाहिए।सामान्य विधि देखने से 'व्यक्ति []' 'के लिए IEnumerable ' एक अंतर्निहित डाली नहीं करता है। जब आप फोन 'person.ToList()' अपने तत्काल प्रकार एक 'सूची ' (यह भी कोई अंतर्निहित कलाकारों की आवश्यकता होती है) है। –

+0

+1 मैं इस मुद्दे के साथ थोड़ा सा झुका रहा हूं। दूसरे शब्दों में – Dan

उत्तर

17

आपके प्रश्न का पहला भाग (सूची-विशिष्ट अधिभार के बिना) आसान है। आइए ऐरे कॉल पर विचार करें, क्योंकि यह दोनों कॉलों के लिए समान काम करता है:

सबसे पहले, टाइप करें कॉल कॉल के दो संभावित जेनेरिक कार्यान्वयन का उत्पादन करता है: Print<Person[]>(Person[] items) और Print<Person>(IEnumerable<Person> items)

फिर ओवरलोड रिज़ॉल्यूशन में शामिल होता है और पहला जीतता है, क्योंकि दूसरे को एक अंतर्निहित रूपांतरण की आवश्यकता होती है, जहां पहला व्यक्ति नहीं करता है (सी # spec के §7.4.2.3 देखें)। सूची तंत्र के लिए एक ही तंत्र काम करता है।

अतिरिक्त अधिभार के साथ, सूची कॉल के साथ तीसरा संभव अधिभार उत्पन्न होता है: Print<Person>(List<Person> items)। तर्क Print<List<Person>>(List<Person> items) लेकिन फिर से साथ के रूप में एक ही है, खंड 7.4.3.2 भाषा

रिकर्सिवली साथ संकल्प, एक का निर्माण प्रकार एक और निर्माण प्रकार की तुलना में अधिक विशिष्ट है (प्रकार तर्कों की एक ही नंबर के साथ) अगर प्रदान करता है कम से कम एक प्रकार का तर्क अधिक विशिष्ट होता है और किसी प्रकार का तर्क दूसरे में संबंधित प्रकार तर्क के मुकाबले कम विशिष्ट नहीं होता है।

तो Print<Person> अधिभार Print<List<Person>> अधिभार की तुलना में अधिक विशिष्ट है और सूची संस्करण IEnumerable से अधिक जीतता है, क्योंकि इसमें कोई अंतर्निहित रूपांतरण की आवश्यकता है।

+0

धन्यवाद है, यह सब अब समझ में आता है – theburningmonk

3

जेनरिक Print(Person[] item) और Print(List<Person> item) से उत्पन्न विधियां IEnumerable<T> से बेहतर मिलान हैं।

संकलक, अपने प्रकार तर्क के आधार पर उन तरीकों पैदा तो सामान्य टेम्प्लेट Print<T>(T item)Print(Person[] item) और Print(List<Person> item) (संकलन पर एक List<Person> अच्छी तरह से, जो कुछ भी प्रकार का प्रतिनिधित्व करता है) के रूप में संकलित किया जाएगा है। इसके कारण, विधि कॉल को संकलक द्वारा विशिष्ट विधि के रूप में हल किया जाएगा जो प्रत्यक्ष प्रकार को स्वीकार करता है, Print(IEnumerable<Peson>) के कार्यान्वयन पर नहीं।

+0

, प्रिंट हमेशा सर्वश्रेष्ठ मैच टी के रूप में देख रहा है कुछ भी हो सकता माना जाएगा? लेकिन अगर आप एक प्रिंट (सूची आइटम) विधि जोड़ने के लिए, कि विधि है कि (persons.ToList) – theburningmonk

+0

इसके अलावा प्रिंट के लिए कहा जा जाएगा, एरिक Lippert द्वारा इस ब्लॉग पोस्ट के अनुसार, कि कैसे सी # जेनरिक काम नहीं है http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx तुम क्या वर्णित अंतर्निहित कास्टिंग का उल्लेख के लिए सी में टेम्पलेट्स ++ – theburningmonk