2010-02-09 37 views
6

के साथ उपक्रम करना टी के आधार पर जेनेरिक क्लास से "सामान्य" होना संभव है, टी से अधिक सामान्य पर आधारित एक सामान्य वर्ग में?जेनेरिक प्रकार पैरामीटर

उदाहरण के लिए, मेरे पास Derived नामक एक वर्ग है जो Base नाम की कक्षा से प्राप्त होती है। मैंने कभी कुछ इस तरह कर सकते हैं:

List<MyClonableType> specific = new List<MyClonableType>(); 
List<IClonable> general = (List<IClonable>)specific; 

के रूप में यहाँ लिखा, इन उदाहरणों में से प्रत्येक एक InvalidCastException के साथ विफल:

List<Derived> der = new List<Derived>(); 
List<Base> bas = (List<Base>) der; 

या, इंटरफेस का उपयोग कर, यह कभी संभव कुछ इस तरह करना है। जिस प्रश्न के बारे में हम बहस कर रहे हैं वह यह है कि क्या यह वास्तव में असंभव है, या बस एक वाक्यविन्यास त्रुटि है जिसे ठीक किया जा सकता है अगर हम जानते थे कि कैसे।

+0

जावा निर्माण के इस प्रकार के लिए '' है, मुझे आश्चर्य होगा कि सी # समकक्ष नहीं है। – Romain

+1

सी # में समान बाधाओं के लिए सामान्य बाधाएं (जहां कीवर्ड) है, लेकिन मैं ' मैं सकारात्मक नहीं हूं कि Auraseer के बाद क्या है। वह वास्तव में संग्रह पर भिन्नता का उपयोग करना चाहता है। –

+0

@ रोमेन, वह कास्ट सी # में मान्य नहीं है, लेकिन आप 'विधि प्रक्रिया (सूची सूची) जैसी विधि को परिभाषित कर सकते हैं जहां टी: बेस {...} ' – finnw

उत्तर

3

C# 4.0 will have that feature.

यह इंटरफेस और प्रतिनिधियों जो कुछ नियमों का पालन करना पर सक्षम हो जाएगा। List<T> समर्थित नहीं होगा, क्योंकि यह एक ठोस वर्ग है। IList<T> भी समर्थित नहीं होगा, क्योंकि इसकी विधियां दोनों in और out दोनों स्थितियों में उपयोग करती हैं।

+0

वह लिंक मुझे यह भी सुनिश्चित करने के लिए कहता है कि इस कलाकार को प्री-4.0 की अनुमति नहीं है। यही वही है जो मैं जानना चाहता था। – Auraseer

+0

यहां तक ​​कि .NET 4.0 में यह सूची पर लागू नहीं होगा। – kvb

+0

अच्छा बिंदु। भिन्नता केवल इंटरफेस और प्रतिनिधियों पर समर्थित है। –

0

वहाँ अच्छा LINQ विस्तार है:

der.ToList<Base>(); 
+1

मेरा मानना ​​है कि यह विधि एक नया संग्रह बनाता है। यह उपयोगी हो सकता है कि आपको लिंक मिल गया है, लेकिन यह एक कलाकार के समान नहीं है। – Auraseer

+0

यह सच है कि आप विशेष रूप से IENumberable प्रकारों से इस तरह से निपट सकते हैं, लेकिन प्रश्न पूछने के साथ यह वास्तविक कलाकार नहीं है। इस मामले में, ToList () विधि की एक नई सूची बनाता है और प्रत्येक आइटम को मूल से कास्ट करके इसे भरती है। –

+0

यदि आप केवल * पढ़ने * सूची में जा रहे हैं (जो एकमात्र मामला है जहां कास्ट समझ में आएगा) संभवतः इससे कोई फर्क नहीं पड़ता कि आप एक प्रतिलिपि या मूल पढ़ रहे हैं या नहीं। – finnw

1

यह

List<Derived> der = new List<Derived>(); 
List<Base> bas = (List<Base>)der; 

संभव नहीं है और संभव नहीं होना चाहिए। यहां क्या होता है:

Base b = new Base(); 
bas.Add(b); 

Kaboom! क्या होता है यदि उपरोक्त कानूनी bas केवल der और der देखें Base के उदाहरण नहीं जोड़ सकते हैं जो Add ऐसा करने का प्रयास करेगा। (स्थूलता के लिए, Base रूप Animal और Derived रूप Cat के बारे में सोच, क्योंकि तब आप casted सूची Dog का एक उदाहरण जोड़ सकता है जो यह वास्तव में एक List<Cat> है क्योंकि विफल हो जाएगा यदि आप एक List<Animal> करने के लिए एक List<Cat> डाली नहीं कर सकते।)

इसी कारण से

List<MyClonableType> specific = new List<MyClonableType>(); 
List<IClonable> general = (List<IClonable>)specific; 

कभी भी संभव नहीं होना चाहिए।

C# 4.0 में इनमें से कुछ मुद्दों को covariance and contravariance की धारणा के साथ हल किया जाएगा। उदाहरण के लिए, सी # 4.0 में यह कानूनी हो जाएगा:

List<Derived> der = new List<Derived>(); 
IEnumerable<Base> bas = der; 

इसका कारण यह है IEnumerable<Base> केवल Base के उदाहरण बाहर थूक और के बाद से सभी Derived रों हैं Base रों यह ठीक है। एक और तरीका कहा, IEnumerable<Base> कहता है, "मुझे पता है कि Base के उदाहरणों को कैसे फेंकना है" जबकि List<Derived> कहता है, "मुझे पता है कि Derived के उदाहरणों को कैसे फेंकना है।"लेकिन सभी Derived एस Base एस हैं, इसका मतलब है कि List<Derived> यह भी जानता है कि Base के उदाहरणों को कैसे फेंकना है। इसलिए, इसे IEnumerable<Base> के उदाहरण के लिए असाइन किया जाना चाहिए। यह सी # 4.0 में संभव है। सहप्रसरण का एक उदाहरण है।

मैं तनाव होना चाहिए कि List<T> तरह प्रकार जो तरीकों कि दोनों खाने T रों है के लिए और T यह संभव नहीं है एस थूक से बाहर।

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