2011-12-06 17 views
8

मैं कुछ सलाह की जरूरत है/इस पर मदद, मैं पेड़ से लकड़ी किसी भी अधिक नहीं देख सकता।सी # कास्टिंग जेनरिक (सहप्रसरण और contravariance?)

यह कुछ जेनरिक का उपयोग कर इंटरफेस को लागू करने कक्षाओं का एक सीधे आगे श्रृंखला है।

तब मैं उदाहरण के लिए ठोस प्रकार के कास्ट करने के लिए कोशिश कर रहा हूँ:

MyGenericObject<SomeObject> _obj; 

IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj; 

// अमान्य डाली

मैं सहप्रसरण और contravariance लेकिन बहुत स्पष्ट नहीं के बारे में कुछ लेख पढ़ा है क्यों यह wouldn ' टी संभव हो सकता है, या कैसे यह दौर पाने के लिए?


तो, इस उदाहरण में:

public interface IMyObject<in T> where T : IBaseObject 
{ 
    T Activity { get; set; } 
} 

कार्य नहीं करेगा ...


...., क्योंकि आप नहीं मिलता है और गतिविधि संपत्ति सेट कर सकते हैं ।

इस उदाहरण में, मैं ऐसा करने की जरूरत:

public interface IMyObject<out T> where T : IBaseObject 
    { 
     T Activity { get; } 
    } 

आशा व्यक्त की कि मदद के लिए सभी में मदद करता है किसी को, और धन्यवाद!

+0

कृपया अपने इंटरफ़ेस की परिभाषा दिखाएं –

उत्तर

9

आप केवल तभी ऐसा कर सकते हैं जब आप इंटरफेस को कॉन्वेंट (out) पैरामीटर के रूप में घोषित करते हैं। आप केवल यह है कि अगर पैरामीटर covariantly प्रयोग किया जाता है कर सकते हैं।

उदाहरण के लिए, यदि इंटरफ़ेस IMyGenericObject<T> में T पैरामीटर लेने का कोई तरीका है, तो यह आपको पैरामीटर को कॉन्वेंट के रूप में घोषित करने से रोकता है। इसके विपरीत, यदि वहाँ एक तरीका है कि एक T देता है, कि तुम contravariant के रूप में पैरामीटर घोषित करने से रोकता है।

संपादित

SLaks के जवाब पर अपनी टिप्पणी के जवाब में, मैं सब कुछ एरिक Lippert कभी सह और contravariance पर लिखा है दोहराने के लिए परीक्षा रहा हूँ। http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/ और भी बहुत में अपने जवाब (सबसे हाल ही में https://stackoverflow.com/a/8380213/385844) देखें

संक्षेप में:

आप IList<string>IList<object> है क्योंकि यह एक FileInfo एक IList<object> को पारित करने के लिए कानूनी है डाली नहीं कर सकते हैं, लेकिन यह पारित करने के लिए कानूनी नहीं है एक IList<string> करने के लिए इसे।

आप एक IList<string> के लिए एक IList<object> डाली नहीं कर सकते हैं क्योंकि यह एक IList<string> से किसी आइटम को पुनः प्राप्त करने और एक स्ट्रिंग संदर्भ निर्दिष्ट करने के लिए कानूनी है, लेकिन एक IList<object> एक FileInfo है, जो एक स्ट्रिंग को सौंपा नहीं किया जा सकता है शामिल हो सकता है संदर्भ।

संपादित 2

जब से तुम सलाह के लिए कहा है, यह भी सह और contravariant भागों में अपने इंटरफेस विभाजित करने के लिए संभव है। सूची उदाहरण के साथ जारी रखने के लिए, आपको इन इंटरफेस

public interface ICovariantList<out T> 
{ 
    T this[int index] { get; } 
    //... 
} 

public interface IContravariantList<in T> 
{ 
    T this[int index] { set; } 
    void Add(T item); 
    //... 
} 

public class SomeList<T> : ICovariantList<T>, IContravariantList<T> 
{ 
    //... 
} 

यह आप संदर्भ के आधार covariantly या contravariantly वर्ग का उपयोग करने की अनुमति देता है हो सकता था।

+0

क्रमबद्ध, मदद के लिए धन्यवाद! – sambomartin

+0

@ sambomartin आपका स्वागत है। EDIT 2. – phoog

+0

धन्यवाद में कुछ और सलाह, धन्यवाद, मैंने इस तरह से चिल्लाया कि यद्यपि मुझे अंत में सेटटर की आवश्यकता नहीं है ... लेकिन मुझे अगली बार पता है! – sambomartin

4

आपको इंटरफेस को एक कॉन्वेंट (out) सामान्य पैरामीटर के रूप में घोषित करने की आवश्यकता है।

+2

कॉन्वेंटेट 'आउट' है; contravariant 'in' है। स्मारक और बाहर के लिए "ओ"; contravariant के लिए "एन" और – phoog

+0

ठीक है, धन्यवाद। मेरी अगली समस्या यह है कि संकलक रिपोर्ट करता है: "त्रुटि 1 अमान्य भिन्नता: प्रकार पैरामीटर 'xxx को' xxx covariant 'पर अवास्तविक रूप से मान्य होना चाहिए। जो मैंने पढ़ा है, उससे मुझे इंटरफ़ेस को केवल/invariant पढ़ने की आवश्यकता है। मेरे पास IMyGenericInterface SomeObject SomeObjectInstance {get; set;} कोई विचार है? – sambomartin

+0

@sambomartin: आपको समझने की जरूरत है कि भिन्नता कैसे काम करती है। एक लिखने योग्य संस्करण संपत्ति स्वाभाविक रूप से गैर-प्रकार-सुरक्षित है। – SLaks

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