2013-03-24 8 views
7

में सूचीबद्ध नहीं है मैं एक ऐसी विधि बनाने की कोशिश कर रहा हूं जो उपयोगकर्ता चाहता है कि जिस भी प्रकार की सूची देता है। ऐसा करने के लिए मैं जेनेरिक का उपयोग कर रहा हूं, जिसे मैं बहुत परिचित नहीं हूं इसलिए यह प्रश्न स्पष्ट हो सकता है। समस्या यह है कि इस कोड काम नहीं करता है और त्रुटि संदेश फेंकता Cannot convert type Systems.Collections.Generic.List<CatalogueLibrary.Categories.Brand> to Systems.Collection.Generic.List<T>जेलीक विधि का उपयोग कर सकते हैं लेकिन जेनेरिक विधि

private List<T> ConvertToList<T>(Category cat) 
{    
    switch (cat) 
    { 
     case Category.Brands: 
      return (List<T>)collection.Brands.ToList<Brand>(); 

    } 
    ... 
} 

लेकिन अगर मैं IList बजाय का उपयोग करें, कोई त्रुटि नहीं है।

private IList<T> ConvertToList<T>(Category cat) 
{    
    switch (cat) 
    { 
     case Category.Brands: 
      return (IList<T>)collection.Brands.ToList<Brand>(); 

    } 
    ... 
} 

मैं इस मामले में सूची क्यों नहीं कर सकता लेकिन सूची नहीं कर सकता? संग्रह। ब्रांड्स एक तृतीय पक्ष लाइब्रेरी से BrandCollection प्रकार देता है, इसलिए मुझे नहीं पता कि यह कैसे बनाया गया है। क्या यह हो सकता है कि BrandCollection IList से प्राप्त हो सकता है (बस अनुमान लगाता है कि यह करता है) और इसलिए इसे परिवर्तित किया जा सकता है लेकिन सामान्य सूची में नहीं?

+0

आपको वहां पर प्रकार की बाधाओं को रखना चाहिए! आप सिर्फ कास्टिंग सामान के आसपास नहीं जा सकते हैं। – antonijn

+3

क्या आप सुनिश्चित हैं कि आपका दूसरा उदाहरण 'रिटर्न (IList ) संग्रह नहीं है। ब्रांड्स। लिस्ट (); '? – Matthew

+0

मैं इस काम के बाद देखने के लिए जा रहा था। मैं जेनेरिकों के लिए थोड़ा नया हूं इसलिए लगा कि मैं इसे तब तक छोड़ दूंगा जब तक कि यह कुछ और तोड़ दिया: डी क्या बाधा होगी 'टी: ब्रांड' (और अन्य श्रेणियां)? – XSL

उत्तर

9

चूंकि T पर कोई बाधा नहीं है, इसलिए इसे संकलित समय पर केवल object में परिवर्तित किया जा सकता है। इंटरफ़ेस प्रकारों के लिए कंपाइलर द्वारा जांच नहीं की जाती है क्योंकि सैद्धांतिक रूप से एक नई कक्षा बनाई जा सकती है जो IList<object> लागू करता है और List<Brand> प्राप्त करता है। हालांकि, List<T> पर कास्ट विफल हो जाएगा क्योंकि यह ज्ञात है कि कोई वर्ग नहीं बनाया जा सकता है जो List<object> और List<Brand> दोनों को विरासत में मिला है। हालांकि, आपके मामले में, आप जानते हैं कि T आपके switch कथन के माध्यम से क्या है और कलाकार को मजबूर करना चाहते हैं।

private List<T> ConvertToList<T>(Category cat) 
{    
    switch (cat) 
    { 
     case Category.Brands: 
      return (List<T>)(object)collection.Brands.ToList<Brand>(); 
    } 
} 

बड़ा डिजाइन समस्या यहाँ, हालांकि, कि जेनरिक सबसे अच्छा विकल्प आप T के लिए जाना जाता प्रकार के एक असतत सूची है जब नहीं हैं: इस प्रकार है ऐसा करने के लिए, object पहले के माध्यम से डाली। जेनिक्स बेहतर होते हैं जब T या तो कुछ भी हो सकता है, या मूल प्रकार या इंटरफ़ेस से बाधित हो सकता है। यहाँ, आप बस स्विच बयान की प्रत्येक शाखा के लिए एक अलग विधि लेखन बेहतर होगा:

private List<Brand> ConvertToBrandList() 
{ 
    return collection.Brands.ToList<Brand>(); 
} 

इस के बिना, आप बहुत कम प्रकार सुरक्षा की है। क्या होगा अगर कोई आपकी विधि को ConvertToList<int>(Category.Brands) से कॉल करता है?

+0

स्पष्टीकरण के लिए धन्यवाद। हालांकि 'ऑब्जेक्ट' विधि काम करती है, मैं व्यक्तिगत विधि मार्ग के लिए जाऊंगा। मैं 'ब्रांड' को बाध्य नहीं कर पाऊंगा क्योंकि मुझे पता चला है कि यह एक सीलबंद वर्ग है। – XSL

+0

+1। मुझे लगता है कि असली कारण सी # संदर्भ 6.2.4 के कारण है: "स्पष्ट संदर्भ रूपांतरण हैं ...\t * किसी भी वर्ग-प्रकार एस * से * किसी भी इंटरफ़ेस-प्रकार टी * से, बशर्ते एस को सील नहीं किया गया है और प्रदान किया गया एस एस लागू नहीं करता है। " –

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