2012-09-27 17 views
7

जानने के बिना जेनेरिक लौट रहा है मेरे पास एक ऐसी स्थिति है जहां मेरे पास एक वर्ग है जो किसी सामान्य ऑब्जेक्ट प्रकार के उदाहरण को अपने सामान्य प्रकार पैरामीटर में स्वीकार करता है।टाइप

public abstract BaseClass { ... } 
public DiamondClass : BaseClass { ... } 
public SilverClass : BaseClass { ... } 

public Handler<T> where T : BaseClass { ... } 

मैं इनपुट पर प्रकार को परिभाषित करने के बिना Handler<DiamondClass> या Handler<BaseClass> का एक उदाहरण वापस जाने के लिए एक विधि बनाने के लिए सक्षम होना चाहते हैं: लेआउट कुछ इस तरह है। मैं इन पंक्तियों के साथ कुछ कोशिश की है:

public Handler<BaseClass> GetHandler(HandlerType type) 
{ 
    switch(type) 
    { 
     case HandlerType.Diamond: return new Handler<DiamondClass>(); 
     case HandlerType.Silver: return new Handler<SilverClass>(); 
     default: throw new InvalidOperationException("..."); 
    } 
} 

लेकिन यह काम नहीं करेगा, क्योंकि जाहिरा तौर पर Handler<DiamondClass>Handler<BaseClass> को परोक्ष डाली नहीं होंगे। मैं इसे इस तरह निर्दिष्ट कर सकते हैं:

public Handler<T> GetHandler<T>(HandlerType type) where T : BaseClass 
{ 
    switch(type) 
    { 
     case HandlerType.Diamond: return (Handler<T>)new Handler<DiamondClass>(); 
     case HandlerType.Silver: return (Handler<T>)new Handler<SilverClass>(); 
     default: throw new InvalidOperationException("..."); 
    } 
} 

लेकिन अब मैं GetHandler<DiamondClass> या GetHandler<BaseClass> कॉल करने के लिए की जरूरत है। और यह एक तरीका रखने के उद्देश्य को हरा देता है जो प्रकार को जानने के बिना, एक enum के आधार पर उचित हैंडलर देता है। मुझे आशा थी कि मैं इस तरह के रूप में एक Type वस्तु निर्धारित कर सकते हैं और इसे पारित,:

Type objType = typeof(DiamondClass); 
var handler = Handler<objType>(); 

लेकिन जाहिरा तौर पर सी # मूर्खता उस तरह का अनुमति नहीं दी जाएगी। मैं इस कई अलग-अलग तरीकों से चला गया हूं, और मुझे लगता है कि ऐसा करने का एक तरीका है, लेकिन मैं स्टंप हो गया हूं।


(मैं वास्तव में एक dynamic वस्तु वापस लौट कर इस काम कर पाने के लिए किया था, लेकिन मैं अगर संभव हो यह से बचने के लिए, के रूप में यह किसी भी प्रकार की सुरक्षा और IntelliSense समर्थन खो देता है चाहते हैं।)

+0

'var handler = हैंडलर (); 'में क्या गलत है, मैं नहीं देख रहा हूं कि आप किस समस्या को हल करने की कोशिश कर रहे हैं। – CaffGeek

+3

यदि आपको सामान्य विधि के अंदर प्रकार की जांच करनी है, तो मैं हमेशा इस तरह की विधि की उपयोगिता पर सवाल उठाऊंगा। –

+0

@RobA ध्यान रखें कि मैंने स्पष्टीकरण के लिए उदाहरण को बहुत सरल बना दिया है। समस्या का एक हिस्सा यह है कि मैं इसे उपयोगकर्ता नियंत्रण पर रखना चाहता हूं, और मैं इसे सामान्य रूप से परिभाषित नहीं कर सकता क्योंकि यह डिजाइनर को मारता है। – KChaloux

उत्तर

9

यह वह जगह है जहां सहप्रसरण नाटक, सहप्रसरण और विपरीत विचरण में आता है सिर्फ इंटरफेस और प्रतिनिधि पर काम करते हैं, हां, तो अपनी समस्या को हल करने के लिए, बस एक नए इंटरफ़ेस IHandler रूप सह संस्करणout साथ जो कि प्रकार पैरामीटर निर्दिष्ट करता है परिभाषित सह-संस्करण है:

public interface IHandler<out T> where T : BaseClass 
{ 
} 

कि एक covariant प्रकार पैरामीटर अपने तरीकों प्रकार पैरामीटर

यह काम करेंगे द्वारा निर्दिष्ट की तुलना में अधिक व्युत्पन्न प्रकार वापस जाने के लिए सक्षम बनाता है एक इंटरफेस। अधिक जानकारी here

+2

लिंकyyyy – JonH

+0

हे, मुझे नहीं पता था कि हम प्रकार के साथ ऐसा कर सकते हैं! ठंडी फलियां। मुझे यह सामान सीखना अच्छा लगता है। संपादित करें: बस इसे आजमाया। आप एक जीवन रक्षक है। मैंने अवधारणा के तरीके को सरल बना दिया जो मैंने सोचा था कि मुझे क्या करना है। मैं सोच रहा था कि यह बच्चे को आधार के प्रकार के रूप में क्यों स्वीकार नहीं करेगा। – KChaloux

+0

@KChaloux: क्योंकि अगर मैं आपको सही ढंग से समझता हूं तो यह सामान सिर्फ इंटरफ़ेस और डिलीजेट के साथ काम करता है? इसका मतलब क्या है * बच्चा आधार के प्रकार के रूप में *? –

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