2012-12-09 26 views
6

के लिए अधिभार त्रुटि मैं विभिन्न सामान्य प्रकारों के अनुसार अलग-अलग परिणाम प्राप्त करने के लिए विधियों अधिभार का उपयोग करना चाहता हूं। यह काम नहीं करता। मेरा कोड इसे स्पष्ट रूप से दिखाता है।सी # जेनेरिक प्रकार

static class Helper 
{ 

    public static bool Can(int i) 
    { 
     return true; 
    } 

    public static bool Can(Object o) 
    { 
     return false; 
    } 
} 

class My<T> 
{ 
    public static bool can = Helper.Can(default(T)); 
} 

Console.WriteLine(Helper.Can(default(int)));//True,it is OK 

Console.WriteLine(My<int>.can);//false?? why the overload doesn't work 
Console.WriteLine(My<Object>.can);//false 

My<int> कॉल Helper.Can (वस्तु ओ) के बजाय Helper.Can क्यों (आई इंट)?

उत्तर

4

यह इस तरह से काम नहीं करता है।

ओवरलोड को पूरी तरह से संकलन समय पर हल किया जाता है; जेनेरिक प्रकार पैरामीटर रनटाइम पर हल किए जाते हैं।
चूंकि संकलक को पता नहीं है कि Tint है, तो आपका कोड हमेशा Can(Object) पर कॉल करेगा।

+0

ग्रेट। धन्यवाद – zilong

+0

मैं इस कथन से काफी सहमत नहीं हूं कि "जेनेरिक प्रकार पैरामीटर रनटाइम पर हल किए जाते हैं"। यदि यह मामला था, तो संकलक संकलन समय पर नहीं बता सका कि आपको 'सूची ' से कोई आइटम नहीं मिल सकता है। संकलित समय पर अनसुलझा माना जाता है * जेनेरिक वर्ग के भीतर सामान्य प्रकार पैरामीटर की घटनाएं क्या होती हैं। –

+0

@ ओआर.मैपर: मेरा मतलब सामान्य वर्ग के भीतर था। – SLaks

1

यह एक छोटा सा वर्बोज़ है, लेकिन आप प्राप्त कर सकते थे कि आप क्या चाहते प्रतिबिंब का उपयोग करके:

class My<T> 
{ 
    static bool doStuff() 
    { 
     var rightMehod = typeof(Helper).GetMethods().Where(p => 
      { 
       if (!p.Name.Equals("Can")) 
        return false; 

       if (!p.ReturnType.Equals(typeof(bool))) 
        return false; 

       if (p.GetParameters().Length != 1) 
        return false; 

       var par = p.GetParameters().First(); 
       return par.ParameterType.Equals(typeof(T)); 
      }).FirstOrDefault(); 

     if (rightMehod == null) 
     { 
      return Helper.Can(default(T)); 
     } 
     else 
     { 
      return (bool)rightMehod.Invoke(null, new object[] { default(T) }); 
     } 
    } 

    public static bool can = doStuff(); 
} 

इस तरह,

My<string>.can == false 
My<int>.can == true 
My<object>.can == false 
बेशक

, अतिरिक्त शिल्प का एक सा के साथ (और जेनेरिक प्रकारों का उपयोग), आप कई अलग-अलग स्थितियों के लिए बड़े पैमाने पर उस स्निपेट का पुनः उपयोग करने में सक्षम होंगे।

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

3

आम तौर पर, यह संकलन समय पर वस्तु को हल होगा, लेकिन आप गतिशील कीवर्ड का उपयोग करके क्रम तक इंतजार करने के लिए कह सकते हैं:

class My<T> 
{ 
    public static bool can = CanWithDynamic(); 

    private static bool CanWithDynamic() { 
     dynamic runtimeT = default(T); 
     return Helper.Can(runtimeT); 
} 

तो, यह के लिए काम करेंगे कि तुम क्या कोशिश कर रहे हैं करने के लिए और सही अधिभार कहा जाएगा। हालांकि, रनटाइम पर हल किए गए किसी भी चीज़ के साथ इसके साथ जुड़े प्रदर्शन लागत भी होती है। शायद एक में से अधिक नहीं, लेकिन यदि आप अक्सर इस विधि को कॉल करते हैं तो इसका असर हो सकता है।

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