2017-01-23 4 views
5

में जेनेरिक सूचियों के लिए रूपांतरण टाइप करें मैं यह पता लगाने की कोशिश कर रहा हूं कि पहले मामले में प्रकार रूपांतरण क्यों संभव नहीं है, लेकिन यह दूसरे में संभव है। कृपया, नीचे दिए गए कोड पर एक नज़र डालें:सी #

var strList = new List<string>{"One", "Two", "Three"}; 
List<object> objList = (List<object>) strList; // <<<< why is not converted? - Case 1 

IEnumerable<object> ienumList = strList; // <<<< why is converted? - Case 2 
+5

कॉन्वर्सिस और contravariance को देखो। – HimBromBeere

+1

http://stackoverflow.com/questions/16966961/cannot-convert-from-listderivedclass-to-listbaseclass या http://stackoverflow.com/questions/1817300/convert-listderivedclass-to-listbaseclass देखें। – wkl

+1

यदि आप अभी भी एसए करना चाहते हैं। '' सूची में कलाकारों के समान, आप 'ऑफ़ टाइप टाइप' का उपयोग कर सकते हैं 'कास्ट' – wkl

उत्तर

-1

सह और अनुबंध-भिन्नता के स्पष्टीकरण के लिए निम्नलिखित देखें। लगता है कि यह आपको आ रही समस्या पर स्पष्टता दे देंगे:

http://tomasp.net/blog/variance-explained.aspx/

+2

लिंक केवल उत्तर ही यहां फंस गए हैं। शायद आप उस पृष्ठ से प्रासंगिक विवरण शामिल करने के लिए अपना उत्तर अपडेट कर सकते हैं? – Chris

0

आप ढांचे 3.5 या उच्चतर का उपयोग कर रहे हैं, तो आप ऐसा कर सकते हैं:

var strList = new List<string>{"One", "Two", "Three"}; 
List<object> objList = strList.Cast<object>().ToList(); 

आप @Hagashen नायडू पर एक नज़र ले जा सकते हैं इस मामले के लिए यह एक बहुत अच्छी व्याख्या है।

+1

हालांकि यह कोड शब्द की उस पंक्ति को बनाने का एक तरीका प्रदान करता है, लेकिन वास्तव में इस सवाल का जवाब नहीं देता कि व्यवहार कैसा है। – Chris

+1

@ क्रिस आप सही हैं। मेरी गलती। फिर भी मैं जवाब छोड़ दूंगा क्योंकि यह किसी की मदद कर सकता है। – NicoRiff

9

comment referring to covariance and contravariance अंतर्निहित सिद्धांत के बारे में एक अच्छा बिंदु बना देता है, मैं प्रस्तुत मामले में ठोस प्रभाव के मामले में जवाब देने के लिए जा रहा हूँ:

List<object> objList = (List<object>) strList; 

objList लिखने योग्य है। यह आप ऐसा करने की अनुमति देगा:

objList.Add(new Object()); 

हालांकि, objList अभी भी strList रूप में एक ही उदाहरण है। आपने System.Object का List<string> पर एक उदाहरण जोड़ा है!

कंपाइलर ऐसा होने की अनुमति नहीं दे सकता है। इस प्रकार, List<string> को List<object> पर नहीं डाला जा सकता है।

दूसरे मामले में, दूसरे हाथ पर, आप एक गणनीय पुनः प्राप्त:

IEnumerable<object> ienumList = strList; 

, गणनीय जिसके परिणामस्वरूप संशोधित करने के लिए कोई तरीका नहीं है के रूप में IEnumerable<T> किसी भी सदस्यों को बताया कि उदाहरण उत्परिवर्तित प्रदान नहीं करता है। इसलिए, टाइप पैरामीटर Tout कीवर्ड के साथ चिह्नित किया जा सकता है (और है), जो प्रस्तुत टाइपकास्ट को अनुमति देता है।

2

दो प्रमुख अवधारणाएं भूमिका निभाती हैं: Type Conversions और Generic Interfaces Variance। जहां भिन्नता अग्रणी है।

केस 1:List<T> में वर्ग परिभाषा, हम सामान्य पैरामीटर पर विचरण नहीं है। इसलिए हमारे पास List<object> और List<string> के बीच कोई संबंध परिभाषित नहीं है। वे invariant हैं। इसलिए दोनों निहित और स्पष्ट प्रकार के रूपांतरण संभव नहीं हैं।

केस 2:List<T> औजार IEnumerable<out T> जो covariant सामान्य प्रकार है, इसलिए List<string> परोक्ष IEnumerable<object>

विवरण के लिए डाली जा सकता है:

क्यों विचरण List<T> लिए अनुमति नहीं है, लेकिन IEnumerable<T> के लिए अनुमति दी?

जेनरिक का बिंदु संकलन-समय प्रकार की सुरक्षा प्रदान करना है। क्योंकि List<T> लिखने योग्य है और अगर वहाँ एक संकलन समय जांच नहीं था, हम निम्नलिखित लिख सकते हैं और एक रन-टाइम त्रुटि हो सकता है:

List<string> stringList = new List<string>(); 
stringList.Add("some string"); // we are safe 
List<object> objectList = stringList; 
objectList.Add((new Object()); // Aargh! 
// we are trying to put an object to a list of strings! 

List<T> के लिए तो असुरक्षित विचरण।

लेकिन IEnumerable<out T> केवल पढ़ने के लिए है। यह संदर्भित उदाहरण को संशोधित करने का एक तरीका प्रदान नहीं करता है।

IEnumerable<object> objectList = new List<string>(); 
// we can't add a string to the objectList, 
// as `IEnumerable<out T>` is a read-only interface. 

तो एक सुरक्षित भिन्नता संभव है।

+0

हाय Kalitsov। मैंने कोड मार्कअप के साथ अपने उत्तर को संपादित करने की स्वतंत्रता ली है, इसलिए यह थोड़ा सा neater (साथ ही साथ कुछ व्याकरण सुधार)। भविष्य में इस संदर्भ के संदर्भ में आपको केवल उस पाठ को घेरना होगा जिसे आप बैकटिक्स ('') के साथ कोड के रूप में चिह्नित करना चाहते हैं, जिसका अर्थ यह होगा कि यह इसे कोड के रूप में प्रस्तुत करेगा और '<>' द्वारा भ्रमित नहीं होगा जो कभी-कभी गायब हो जाता है कोड मार्कअप। – Chris

+0

धन्यवाद क्रिस! मैं घूम रहा था कि यह कैसे करें। – Kalitsov

+0

संपादक भी आपके लिए यह करेगा। यदि आप पैराग्राफ में टेक्स्ट को हाइलाइट करते हैं (पूर्ण अनुच्छेदों के बजाए) और शीर्ष पर कोड बटन दबाएं ('{}' जैसा दिखता है) तो यह आपके लिए बैकटिक्स लगाएगा। – Chris