यह प्रकार का अनुमान नहीं लगा सकता है, क्योंकि इस प्रकार को यहां परिभाषित नहीं किया गया है।
Fun2
Func<string, string>
नहीं है, हालांकि ऐसा कुछ है जिसे Func<string, string>
पर असाइन किया जा सकता है।
तो अगर आप का उपयोग करें:
public Test()
{
Func<string, string> del = Fun2;
Fun(del);
}
या:
public Test()
{
Fun((Func<string, string>)Fun2);
}
तो आप स्पष्ट रूप से Fun2
से एक Func<string, string>
बना रहे हैं तथा सामान्य प्रकार अनुमान के हिसाब से काम करता है।
इसके विपरीत, जब आप ऐसा करेंगे:
public Test()
{
Fun<string>(Fun2);
}
तब भार के Fun<string>
के सेट केवल एक ही है कि एक Func<string, string>
स्वीकार करता है और संकलक अनुमान लगा सकते हैं कि आप इस तरह के रूप Fun2
उपयोग करना चाहते हैं।
लेकिन आप तर्क के प्रकार के आधार पर जेनेरिक प्रकार, और जेनेरिक प्रकार के आधार पर तर्क के प्रकार का अनुमान लगाने के लिए कह रहे हैं। यह किसी भी तरह की अनुमान के मुकाबले एक बड़ा सवाल है जो यह कर सकता है।
(यह न केवल थे .NET 1.0 में है कि विचार के लायक है प्रतिनिधियों नहीं सामान्य-ताकि आप -लेकिन यह भी जरूरी हो गया था एक निर्माता Fun(new MyDelegate(Fun2))
साथ वस्तु बनाने के लिए delgate string MyDelegate(string test)
परिभाषित करने के लिए था। वाक्य रचना उपयोग करने के लिए बदल गया है प्रतिनिधियों के कई तरीकों से आसान है, लेकिन Fun2
के Func<string, string>
के अंतर्निहित उपयोग अभी भी दृश्यों के पीछे एक प्रतिनिधि वस्तु का निर्माण है)।
फिर यह क्यों काम करता है?
class Test
{
public void Fun<T1, T2>(T1 a, Func<T1, T2> f)
{
}
public string Fun2(int test)
{
return test.ToString();
}
public Test()
{
Fun(0, Fun2);
}
}
क्योंकि तब यह अनुमान लगा सकते हैं, क्रम में:
T1
int
है।
Fun2
को T2
के लिए Func<int, T2>
पर असाइन किया जा रहा है।
Fun2
Func<int, T2>
को T2
string
पर असाइन किया जा सकता है। इसलिए T2
स्ट्रिंग है।
विशेष रूप से, Func
के वापसी प्रकार को आपके द्वारा तर्क प्रकार होने के बाद एक फ़ंक्शन से अनुमानित किया जा सकता है। यह भी ठीक है (और संकलक के हिस्से पर प्रयास के लायक है) क्योंकि यह लिंक के Select
में महत्वपूर्ण है। इससे संबंधित मामला सामने आता है, तथ्य यह है कि x.Select(i => i.ToString())
के साथ हमारे पास यह जानने के लिए पर्याप्त जानकारी नहीं है कि लैम्ब्डा को क्या डाला जाता है। एक बार जब हम जानते हैं कि x
IEnumerable<T>
या IQueryable<T>
हम जानते हैं कि हमारे पास Func<T, ?>
या Expression<Func<T, ?>>
है और शेष को वहां से अनुमानित किया जा सकता है।
यह भी ध्यान देने योग्य है कि रिटर्न प्रकार को कम करना एक अस्पष्टता के अधीन नहीं है जो अन्य प्रकारों को कम करता है। इस बात पर विचार करें कि क्या हमारे पास Fun2
(वह एक है जो string
और एक ही कक्षा में int
) लेता है। यह मान्य सी # ओवरलोडिंग है, लेकिन Func<T, string>
के प्रकार की कटौती करता है कि Fun2
असंभव में डाला जा सकता है; दोनों मान्य हैं।
हालांकि, जबकि .NET रिटर्न प्रकार पर ओवरलोडिंग की अनुमति देता है, सी # नहीं करता है। इसलिए T
के प्रकार को निर्धारित करने के बाद एक विधि (या लैम्बडा) से बनाए गए Func<T, TResult>
के रिटर्न प्रकार पर कोई मान्य सी # प्रोग्राम संदिग्ध नहीं हो सकता है। उस सापेक्ष आसानी, महान उपयोगिता के साथ मिलकर, यह कुछ बनाता है जो संकलक हमारे लिए अनुमान लगाने के लिए अच्छा है।
अपने संपादन को पुनः पढ़ें, अब आपने 'Fun (0, Fun2);' कॉल के माध्यम से संकलक की आपूर्ति की है। कंपाइलर अब जानता है कि इसे 'Fun2' विधि समूह' से एक विधि की आवश्यकता है, जिसमें 'T1' प्रकार है, इस मामले में' int'। यह इसे एक विधि तक सीमित करता है और इसलिए यह अनुमान लगा सकता है कि किस का उपयोग करना है। –
लेकिन पहली जगह में एक Fun2 है, इसलिए यह वास्तव में कुछ भी संकीर्ण नहीं करता है। –
सी # कंपाइलर एक विधि समूह के इलाज के लिए मना कर देता है जिसमें एक प्रतिनिधि के रूप में केवल एक विधि होती है। ऐसा करने के लिए आपको परेशान करने के लिए समूह से एक विधि का चयन करने के लिए आपको जानकारी प्रदान करनी होगी। यह बहुत अच्छा होगा अगर उसने समूह को देखा, एहसास हुआ कि केवल एक विधि थी और इसे चुना गया, लेकिन दुख की बात यह है कि यह कैसे काम करता है। –