2011-07-19 9 views
14
public abstract class EntityBase { ... } 

public interface IFoobar 
{ 
    void Foo<T>(int x) 
     where T : EntityBase, new(); 
} 

public interface IFoobar<T> 
    where T : EntityBase, new() 
{ 
    void Foo(int x); 
} 

public class Foobar<T> : IFoobar, IFoobar<T> 
    where T : EntityBase, new() 
{ 
    public void Foo(int x) { ... } 

    void IFoobar.Foo<T>(int x) { Foo(x); } 
} 

मैं एक संकलक चेतावनी मिलती है के रूप में एक ही नाम है गारंटी है कि यू और टी समान हैं। जिस तरह से फूबर वर्ग लागू किया गया है, यह बहुत महत्वपूर्ण है कि वे वही हों।प्रकार पैरामीटर 'टी' बाहरी प्रकार से प्रकार पैरामीटर '...'

मैंने यह भी करने की कोशिश की: void IFoobar.Foo<U>(int x) where U : T { Foo(x); }, हालांकि यह गारंटी नहीं देता है कि यू और टी बराबर हैं और यह इंटरफ़ेस पर परिभाषित होने के बाद से बाधा को फिर से परिभाषित करने की अनुमति नहीं देता है।

+0

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

उत्तर

8

आप क्या कर सकते हैं दो चीजों में से एक:

  1. चेतावनी को अनदेखा करें और दोनों प्रकार के टी
  2. एक रन-टाइम की जाँच करें बनाने के लिए और फेंक एक अपवाद:

    if (typeof(T) != typeof(U)) throw Exception("Not the same type"); 
    

के रूप में दूसरों ने कहा है, शायद आप जिस तरह से आप कर रहे हैं पुनर्विचार करने की आवश्यकता अपने इंटरफेस डिजाइनिंग।

3

बस

void IFoobar.Foo<U>(int x) { Foo(x); } 
बेशक

, अभी भी गारंटी नहीं है कि कि UT रूप में ही है की कोशिश करो। आप संकलित समय पर लागू नहीं कर सकते हैं, क्योंकि जब आप एक इंटरफ़ेस को कार्यान्वित कर रहे हैं, तो आप अपने नियमों का पालन करना चाहिए - और IFoobarFoo<T> पर ऐसा प्रतिबंध नहीं लगाता है, और यदि आप करते हैं, तो आप करेंगे इंटरफ़ेस को कार्यान्वित नहीं किया जा रहा है (परिभाषा के अनुसार, क्योंकि आप कठोर हैं, और फिर भी आप दावा कर रहे हैं कि आप नहीं हैं)।

आप इसे रन टाइम पर जांचने का प्रयास कर सकते हैं, हालांकि यह कुछ हद तक "धोखाधड़ी" है (क्योंकि आप वास्तव में इंटरफ़ेस के अनुरूप नहीं हैं)।

+0

जबकि यह इस प्रकार की बाधा को बनाए रखता है, यह गारंटी नहीं देता है कि 'टी' और' यू' समान हैं। –

+0

यह गारंटी नहीं देता है कि यू टी के बराबर है, और मैं इंटरफ़ेस में परिभाषित होने के बाद से यू पर बाधाओं को फिर से परिभाषित नहीं कर सकता। – michael

+0

यह संकलित नहीं होगा। 'ओवरराइड और स्पष्ट इंटरफ़ेस कार्यान्वयन विधियों के लिए बाधा बेस विधि से विरासत में प्राप्त होती है, इसलिए उन्हें सीधे निर्दिष्ट नहीं किया जा सकता है। इसे ठीक करने के लिए कहां निकालें। –

12

सबसे बड़ी समस्या यह है कि आपके इंटरफेस अच्छी तरह परिभाषित नहीं हैं, और आपके कोड के इरादे से मेल नहीं खाते हैं।

यदि आपका T इंटरफ़ेस पर सार्वजनिक रूप से दिखाई नहीं दे रहा है, तो बाहरी कोड को यह भी पता नहीं होना चाहिए कि T है। आपको या तो T प्राप्त करने या वापस करने की विधियों को बनाने की आवश्यकता है, या T टाइप की कुछ संपत्ति है, या आपको पूरी तरह से T से छुटकारा पाना चाहिए, और अपने इंटरफेस को गैर-जेनेरिक बनाना चाहिए।

एक बार जब आप इसे किनारे बनाते हैं, तो यह और स्पष्ट हो जाना चाहिए कि आपको यहां दो अलग-अलग इंटरफेस की आवश्यकता क्यों नहीं है, और आपको अब उन्हें मेल नहीं करना चाहिए।

यह पता चला है कि आप एक संस्करण है कि T लेता है, और एक गैर-टी संस्करण है, तो यह करने के लिए अधिक मुहावरेदार तरीके की आवश्यकता objectT के चारों ओर के बजाय पारित करना हैं:

public interface IFoo 
{ 
    void DoSomething(object o); 
    object DoSomethingElse(); 
} 

public interface IFoo<T> 
{ 
    void DoSomething(T item); 
    T DoSomethingElse(); 
} 

इस उदाहरण के लिए IEnumerable, ICollection, IList आदि जैसे इंटरफेस देखें।

लेकिन ध्यान से पर विचार करें। यह अंतिम डिजाइन समझौता (एक जेनेरिक और ऑब्जेक्ट संस्करण दोनों होने के बाद) हमेशा वांछित होने के लिए कुछ छोड़ देता है।

आप इनमें से किसी एक का त्याग करेंगे:

  • अच्छा इंटरफेस डिजाइन कि सीधे एक डिजाइन अनुबंध संचार (आप अपवाद फेंक या जब गलत प्रकार में पारित हो जाता है नो-सेशन करते हैं)
  • प्रकार सुरक्षा, और कीड़े में कमी है कि यह साथ चला जाता है (यदि आप सही ढंग से किसी भी पुरानी-वस्तु पर कार्य करते हैं)