2012-06-08 25 views
121

<out T> और <T> के बीच क्या अंतर है? उदाहरण के लिए:<out T> बनाम <T> जेनिक्स

public interface IExample<out T> 
{ 
    ... 
} 

बनाम

public interface IExample<T> 
{ 
    ... 
} 

केवल जानकारी मैं MSDN से मिल गया है कि

आप सामान्य इंटरफेस और प्रतिनिधियों में कीवर्ड का उपयोग कर सकते थे।

+1

अच्छा उदाहरण IObservable होगा और IObserver , परिभाषित mscorlib में सिस्टम एनएस में। सार्वजनिक इंटरफ़ेस IObservable , और सार्वजनिक इंटरफ़ेस IObserver । इसी तरह, आईनेमेरेटर , आईनेमेरेबल VivekDev

उत्तर

158

जेनरिक में out कीवर्ड निरूपित करने के लिए है कि इंटरफ़ेस में प्रकार टी covariant है प्रयोग किया जाता है। विवरण के लिए Covariance and contravariance देखें।

क्लासिक उदाहरण IEnumerable<out T> है। चूंकि IEnumerable<out T> covariant है, तो आप निम्न कार्य करने की अनुमति हो:

IEnumerable<string> strings = new List<string>(); 
IEnumerable<object> objects = strings; 

अगर यह covariant नहीं कर रहा था ऊपर दूसरी पंक्ति विफल हो जाएगा, यहां तक ​​कि तार्किक हालांकि यह काम करना चाहिए, के बाद से स्ट्रिंग वस्तु से निकला है। variance in generic interfaces से पहले C# और VB.NET में जोड़ा गया था (वीईएस 2010 के साथ .NET 4 में), यह एक संकलित समय त्रुटि थी।

.NET 4, IEnumerable<T> के बाद कॉन्वेंट चिह्नित किया गया था, और IEnumerable<out T> बन गया। चूंकि IEnumerable<out T> केवल इसके भीतर के तत्वों का उपयोग करता है, और उन्हें कभी भी जोड़ता/बदलता नहीं है, यह वस्तुओं के एक गणना संग्रह के रूप में तारों के एक गणना संग्रह का इलाज करने के लिए सुरक्षित है, जिसका अर्थ यह है कि यह कॉन्वर्स है।

यह IList<T> जैसे किसी प्रकार के साथ काम नहीं करेगा, क्योंकि IList<T> में Add विधि है। मान लीजिए यह अनुमति दी जाएगी:

IList<string> strings = new List<string>(); 
IList<object> objects = strings; // NOTE: Fails at compile time 

फिर आप कह सकते हैं:

objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object 

यह, ज़ाहिर है, विफल हो जाएगा - तो IList<T> चिह्नित नहीं किया जा सकता covariant।

in के लिए एक विकल्प भी है, जिसका उपयोग तुलना इंटरफेस जैसी चीजों द्वारा किया जाता है।IComparer<in T>, उदाहरण के लिए, विपरीत तरीके से काम करता है।का उप-वर्ग है, क्योंकि IComparer<in T> इंटरफ़ेस contravariant है, तो आप को सीधे IComparer<Bar> के रूप में एक ठोस IComparer<Foo> का उपयोग कर सकते हैं।

+3

@ कोलेजोहनसन क्योंकि 'छवि' एक सार वर्ग है;) आप' नई सूची () {Image.FromFile ("test.jpg")} कर सकते हैं; 'कोई समस्या नहीं है, या आप कर सकते हैं 'नई सूची () {नया बिटमैप ("test.jpg")};' साथ ही करें। आपकी समस्या यह है कि 'नई छवि() 'की अनुमति नहीं है (आप' var img = new image(); 'या तो नहीं कर सकते) –

+3

एक सामान्य' IList 'एक विचित्र उदाहरण है, यदि आप' ऑब्जेक्ट की आपको जेनिक्स की आवश्यकता नहीं है। – Jodrell

+3

@ReedCopsey क्या आप अपनी टिप्पणी में अपने उत्तर का विरोध नहीं कर रहे हैं? – MarioDS

5

लिंक आप पोस्ट से ....

सामान्य प्रकार पैरामीटर के लिए, बाहर कीवर्ड निर्दिष्ट करता है कि प्रकार पैरामीटर covariant है।

संपादित: फिर, लिंक से आपको

तैनात अधिक जानकारी के लिए, सहप्रसरण और contravariance (सी # और विजुअल बेसिक)। http://msdn.microsoft.com/en-us/library/ee207183.aspx

23

"out T" का अर्थ है कि T टाइप करें "covariant"। यह जेनेरिक क्लास, इंटरफ़ेस या विधि के तरीकों में केवल लौटा (आउटबाउंड) मान के रूप में दिखाई देने के लिए T को प्रतिबंधित करता है। निहितार्थ यह है कि आप प्रकार/इंटरफ़ेस/विधि को सुपर-प्रकार T के बराबर समतुल्य में डाल सकते हैं।
उदा। ICovariant<out Dog> को ICovariant<Animal> पर डाला जा सकता है।

+4

मुझे एहसास नहीं हुआ कि 'बाहर' लागू करता है कि 'टी' केवल तब तक वापस किया जा सकता है जब तक कि मैं यह उत्तर नहीं पढ़ता। पूरी अवधारणा अब और अधिक समझ में आता है! – MarioDS

35

पर विचार करें,

class Fruit {} 

class Banana : Fruit {} 

interface ICovariantSkinned<out T> {} 

interface ISkinned<T> {} 

और काम करता है,

void Peel(ISkinned<Fruit> skinned) { } 

void Peel(ICovariantSkinned<Fruit> skinned) { } 

समारोह है कि स्वीकार करता है ICovariantSkinned<Fruit>ICovariantSkinned<Fruit> या ICovariantSkinned<Bananna> स्वीकार करने के लिए क्योंकि ICovariantSkinned<T> एक covariant इंटरफेस और Banana है में सक्षम हो जाएगा Fruit का एक प्रकार है ,

जो समारोह स्वीकार करता है एस ISkinned<Fruit> केवल ISkinned<Fruit> स्वीकार करने में सक्षम होंगे।

36

in की आसानी से उपयोग और out कीवर्ड (भी सहप्रसरण और contravariance), हम रैपिंग के रूप में छवि विरासत कर सकते हैं याद के लिए:

String : Object 
Bar : Foo 

in/out

+0

यह इसे इतना स्पष्ट बनाता है। – antiduh

+4

क्या यह गलत तरीका नहीं है? Contravariance = in = अधिक व्युत्पन्न प्रकारों को अधिक व्युत्पन्न स्थान के स्थान पर उपयोग करने की अनुमति देता है। /कोविरियन = आउट = कम व्युत्पन्न के स्थान पर अधिक व्युत्पन्न प्रकारों का उपयोग करने की अनुमति देता है। व्यक्तिगत रूप से, अपने आरेख को देखते हुए, मैंने इसे इसके विपरीत के रूप में पढ़ा। –

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