2011-07-15 11 views
6

संभव डुप्लिकेट:एक ही प्रकार के पैरामीटर के लिए दोनों सहप्रसरण और contravariance सहायक

interface ICovariant<out R> 
:

Covariance and Contravariance on the same type argument

आप out कीवर्ड का उपयोग करके covariant के रूप में एक सामान्य प्रकार पैरामीटर घोषणा कर सकते हैं

आप एक सामान्य प्रकार पैरामीटर को contravaria के रूप में घोषित कर सकते हैं NT in कीवर्ड का उपयोग करके:

interface IContravariant<in R> 

और तुम भी विभिन्न प्रकार पैरामीटर के लिए दोनों का समर्थन कर सकते हैं:

interface IVariant<out R, in A> 

तो क्यों तुम दोनों एक ही प्रकार के पैरामीटर के लिए suport नहीं कर सकते?

+2

जेम्स, आप आज भिन्नता में रूचि रखते हैं। आप इस फीचर को डिज़ाइन करने के तरीके के बारे में लेखों और वीडियो की मेरी विशाल श्रृंखला को देखना चाहेंगे। वे यहां हैं: http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/default.aspx, नीचे से शुरू करें। –

उत्तर

7

तो आप एक ही प्रकार के पैरामीटर के लिए दोनों का समर्थन क्यों नहीं कर सकते?

ध्यान रखें कि एक इंटरफेस सिर्फ एक प्रकार पैरामीटर में covariant जा सकता है अगर उस प्रकार पैरामीटर उत्पादन के लिए सुरक्षित है और एक इंटरफेस सिर्फ एक प्रकार पैरामीटर में contravariant जा सकता है अगर उस प्रकार पैरामीटर इनपुट-सुरक्षित है रखें।

वाक्यविन्यास out T कहता है कि T एक कॉन्वेंट प्रकार प्रकार पैरामीटर है।

वाक्यविन्यास in T कहता है कि T एक contravariant प्रकार पैरामीटर है।

T एक कॉन्वेंट प्रकार प्रकार पैरामीटर है, यह परिभाषा इनपुट-असुरक्षित है।

T एक contravariant प्रकार पैरामीटर है, यह परिभाषा आउटपुट-असुरक्षित है।

इसलिए, T इनपुट-असुरक्षित और आउटपुट-असुरक्षित है।

परिणामस्वरूप, T इनपुट स्थिति में निषिद्ध है, और T आउटपुट स्थिति में निषिद्ध है।

इसलिए, T इनपुट स्थिति में और इंटरफ़ेस द्वारा निर्दिष्ट किसी भी तरीके पर किसी भी आउटपुट स्थिति में प्रकट नहीं हो सकता है।

परिणामस्वरूप, T इंटरफ़ेस पर बिल्कुल उपयोग नहीं किया जा सकता है, और एक प्रकार पैरामीटर के रूप में व्यर्थ है।

IFoo<Cat> cat = (IFoo<Animal>)new Foo<Dog>(); 

(आप को पढ़ने के लिए की जरूरत है: नतीजतन, भाषा डिजाइनरों भी इस तरह के एक बेकार प्रकार दोनों covariant और इंटरफेस पर contravariant बदसूरत

interface IFoo<in and out T> { } 
Foo<T> : IFoo<T> { } 

और फिर से बचने के लिए के रूप में चिह्नित सहित करने से रोक इनपुट-सुरक्षित और आउटपुट-सुरक्षित पर, भाषा विनिर्देश के 13.1.3.1 देखें।)

+0

वाह यह पढ़ने के लिए एक कठिन जवाब है :) – JonH

+0

@ जोनएच: धन्यवाद, मैंने फिर कोशिश की। आप क्या सोचते हैं मुझे बताओ? – jason

+0

@ जेसन +1 अच्छा उत्तर – JonH

3

यह काम नहीं करेगा।इस पर विचार करें (यदि in out अस्तित्व में):

public class INewList<in out T> 
{ 
    public T DoIt(T item); 
} 

यह संतुष्ट करना असंभव होगा क्योंकि एक INewList<T> उम्मीद कर लोगों को दोनों संकरा और व्यापक प्रकार के साथ इंटरफेस के साथ संगत होगा।

INewList<Feline> पर विचार करें:

हैं/बाहर दोनों संभव थे में, इस इंटरफेस INewList<Animal> के बराबर होगा, लेकिन यह अवैध के लिए स्थिति में है क्योंकि यह आप तर्क टाइप करने के लिए चौड़ा करने की अनुमति होगी होगा:

... DoIt(Animal item) 

जो काम नहीं करेगा क्योंकि इसका मतलब यह होगा कि आप new Dog() उदाहरण में पारित कर सकते हैं जहां मूल इंटरफ़ेस से एक फ़ेलिन की अपेक्षा की गई थी।

इसी तरह बाहर पदों पर रिवर्स में है क्योंकि यह अनुमति होगी:

Puma DoIt(...) 

कौन सा अमान्य होगा क्योंकि मूल इंटरफ़ेस वापस किसी भी बिल्ली, जरूरी नहीं कि एक प्यूमा दे सकते हैं।

+0

क्षमा करें इससे पहले कि मैंने देखा कि @ जेसन ने पहले ही जवाब दिया था, मैं अपने जवाब का काम कर रहा था। –

+0

क्षमा न करें :-) हमेशा एक ही चीज़ का एक अलग तरीका होना अच्छा लगता है। –

+0

@ जेम्स माइकल हरे: हा! और मैंने आपका जवाब बिना किसी छोटी बिल्ली/कुत्ते के उदाहरण को शामिल करने के लिए अपना जवाब परिष्कृत किया! – jason