2013-02-26 25 views
9

पैरामीटर तो, मैं Servy (https://stackoverflow.com/a/15098242/496680) द्वारा एक जवाब भर में भाग गया और उसकी कोड के कुछ ऐसा करता है: एक विस्तार विधि के लिएक्या लगाए गए सामान्य प्रकार

public static int BinarySearch<TSource, TKey>(...) 

है, लेकिन वह इसे इस तरह कहता है:

arr.BinarySearch(...) 

मैंने चारों ओर पूछा और किसी ने यह पाया कि इसका एक अंतर्निहित सामान्य प्रकार पैरामीटर है। मैंने उन्हें गुगल किया लेकिन उन पर कोई जानकारी नहीं मिली। मैं समझता हूं कि जेनेरिक कैसे काम करते हैं लेकिन मैं यह समझने में असफल रहा हूं कि इनका उपयोग कब/कब किया जाए।

  1. servy उनकी विस्तार विधि में उनका उपयोग क्यों करता है?
  2. क्या उनके लिए कोई और आधिकारिक नाम है जिसके लिए मैं खोज कर सकता हूं?
+2

मैं बस # 1 का उत्तर दे सकता हूं। यह स्ट्रिंग या इनट्स या फूओ या जो भी हो, केवल काम करने के बजाए, किसी भी प्रकार के संग्रह के साथ काम करने की विधि को अनुमति देता है। यह आपको किसी भी प्रकार के मूल्य के साथ तुलना करने की अनुमति देता है, इसे एक int या स्ट्रिंग या बार या [...] दें। आपके विशिष्ट मामले में आपको किसी प्रकार की सरणी से 'int' चुनने की आवश्यकता है (जिसे मैंने आपको दिमाग का नाम भी नहीं बताया था)। जेनेरिक का उपयोग करना यह न केवल आपके एक मामले के लिए काम करेगा, लेकिन किसी भी समान मामले में एक ही समस्या है लेकिन विभिन्न प्रकार के साथ। यह भविष्य में आने वाले आगंतुकों के लिए आपका प्रश्न ढूंढने में अधिक सहायक होगा। – Servy

+0

@ सर्वी धन्यवाद! भविष्य के पाठकों के लिए मुझे यह पोस्ट भी मिला: http://stackoverflow.com/questions/4885027/how-does-generic-type-inference-work-in-c –

उत्तर

10

ठीक है, आपने सबसे महत्वपूर्ण हिस्सा छोड़ दिया है जो इसे सभी काम करता है। प्रकार पैरामीटर में पारित वास्तविक वस्तु मापदंडों से अनुमान लगाया जा सकता

उदाहरण के लिए:।

static class Extensions { 
    internal static IEnumerable<U> Test<T, U>(
            this IEnumerable<T> items, 
            Func<T, U> converter) { 
    foreach (T item in items) { 
     yield return converter(item); 
    } 
    } 
} 

इस विस्तार विधि किसी भी IEnumerable वर्ग पर काम करता है और एक अन्य प्रकार के आधार पर करने के लिए गणन में प्रत्येक आइटम में परिवर्तित कर देंगे आपके द्वारा प्रदान किए गए कनवर्टर पर। यह मानक जेनेरिक है।

IEnumerable<int> values = Enumerable.Range<int>(1, 10); 
Func<int, string> converter = i => i.ToString("0.00"); 

// Variation 1, explicit calling 
IEnumerable<string> results1 = Extensions.Test<int, string>(values, converter); 

// Variation 2, explicit calling with type inference 
IEnumerable<string> results2 = Extensions.Test(values, converter); 

// Variation 3, extension method calling, still providing explicit types 
IEnumerable<string> results3 = values.Test<int, string>(converter); 

// Variation 4, extension method with type inference 
IEnumerable<string> results4 = values.Test(converter); 

सभी चार रूपों में एक ही विधि कॉल और एक ही परिणाम देते हैं:

अब, वहाँ इस विधि कॉल करने के कई तरीके हैं। टाइप किए गए मापदंडों को देखकर अनुमान लगाएं और स्वचालित रूप से उनके प्रकारों को किस प्रकार प्रदान किया जा रहा है, इस पर आधारित है। ऊपर दिए गए हमारे उदाहरणों में, यह निर्धारित करने में सक्षम है कि T टाइप int है क्योंकि हम IEnumerable<T> के पैरामीटर में IEnumerable<int> में पास हुए हैं। यह अनुमान लगा सकता है कि U प्रकार string प्रकार है क्योंकि हम T के प्रारंभिक प्रकार int के साथ मिलान करने और एक स्ट्रिंग लौटने के साथ एक फ़ंक में पारित हो गए हैं। तो Func<T, U>Func<int, string> के हमारे कनवर्टर फ़ंक्शन के साथ भर गया है।

उपरोक्त अनुमान से, यह उस बिंदु पर एक मानक सामान्य विधि है। टाइप अनुमान और विस्तार विधियां सुविधा/वाक्य रचनात्मक चीनी से अधिक कुछ नहीं हैं।वास्तव में, यदि आप आउटपुट को कम करते हैं तो आप देख सकते हैं कि एक्सटेंशन विधियों को स्थिर कॉल के साथ प्रतिस्थापित किया गया है और आमतौर पर स्पष्ट रूप से भरे गए पैरामीटर के साथ परिभाषित किया जाता है। (यह आपके डिकंपेलर और सेट विकल्पों के आधार पर भिन्न होता है)।

+0

आपके पिछले दो उदाहरणों के लिए आपको पैरामीटर के रूप में 'मानों' को छोड़ना होगा। – Servy

+0

ओह, धन्यवाद! जब आप संकलित नहीं कर सकते तो यह आश्चर्यजनक है कि आप क्या याद कर सकते हैं! – Joshua

+0

ग्रेट स्पष्टीकरण! धन्यवाद! –

2

शब्द जो मैं आमतौर पर सुनता हूं वह 'प्रकार अनुमान' है।

+0

हां, इसे "टाइप अनुमान" कहा जाता है। [जेनेरिक तरीके (सी # प्रोग्रामिंग गाइड)] (http://msdn.microsoft.com/en-us/library/twcad0zb.aspx) पर एक पूरी तरह से मूल उदाहरण है जहां यह कहता है: _ आप टाइप तर्क और कंपाइलर को भी छोड़ सकते हैं ** ** अनुमान लगाएगा **। स्वैप के लिए निम्न कॉल पिछले कॉल के बराबर है: [...] प्रकार के अनुमान के लिए समान नियम स्थिर विधियों और उदाहरण विधियों पर लागू होते हैं। संकलक आपके द्वारा पारित विधि तर्कों के आधार पर प्रकार पैरामीटर का अनुमान लगा सकता है; यह केवल बाधाओं या वापसी मूल्य से प्रकार पैरामीटर का अनुमान नहीं लगा सकता है। [...] _ –

6
  1. वह इस मामले में एक generic method का उपयोग करता है, क्योंकि यह उसकी विधि किसी भी प्रकार के एक Collection<T> के भीतर निहित के साथ काम करने की अनुमति देता है। जेनेरिक विधि यह बहुत लचीला बनाता है, और किसी भी प्रकार के लिए प्रयोग योग्य बनाता है। विधि को कॉल करते समय वह प्रकार के उल्लंघन का उपयोग करता है क्योंकि यह कॉल साइट पर कोड को सरल बनाता है।

  2. स्वचालित हैंडलिंग को टाइप इन्फेरेंस कहा जाता है, और सी # भाषा विशिष्टता, खंड 7.5.2 में विस्तार से कवर किया गया है: टाइप अंतरण। यदि आप इसे विस्तार से समझना चाहते हैं, तो मैं C# language specification डाउनलोड करने की अनुशंसा करता हूं।

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