2012-01-26 8 views
10

मैं कैसे मेरी समस्या कहा जाता है पता नहीं है के रूप में के बारे में, मैं गारंटी नहीं दे सकते, कि कोई भी एक ही सवाल हाल ही में या बिल्कुल भी कहा है।जेनेरिक्स और विरासत (मेरा बुरा शीर्षक माफ)

मैं नोटिस किया था, एक ऐसी ही शीर्षक के साथ काफी कुछ धागे देखते हैं तथापि कि है, लेकिन वे अपनी समस्या के लिए प्रासंगिक हो नहीं है।

मेरे पास एक कस्टम सूची वर्ग है, जो जेनरिक लागू करता है।

class MyList<T> 
{ 
    public void add(T item) // adds an item to the list 
    { /* code */ } 
    public void add(MyList<T> list) // attaches an existing list to the end of the current one 
    { /* code */ } 
} 

मैं भी श्रेणियां होती हैं:

MyList<Fruit> fruitList = new MyList<Fruit>(); 
// fill fruitList 

fruitList.add(new Apple()); // works, of course 
fruitList.add(new Banana()); // works as well, of course 

MyList<Apple> appleList = new MyList<Apple>(); 
// fill appleList 

fruitList.add(appleList); // doesn't work. Why? 

हालांकि appleList एक MyList है (के:

class Apple : Fruit 

और

class Banana : Fruit 
अब

, प्रासंगिक कोड आता है ऐप्पल) और ऐप्पल फल है, विजुअलस्टूडियो Accep नहीं है टी MyList (एप्पल के) तर्क के रूप में, जब MyList (फल का) पूछा जाता है।

हालांकि, अगर मैं इस तरह की सूची घोषित करने के लिए किए गए:

MyList<object> fruitList = new MyList<object>(); 

तब सब कुछ फिर से काम करता है। मैंने वास्तव में क्या गलत किया?

एक उत्तर बहुत सराहना की जाएगी, और समय, पढ़ने के लिए भी जवाब दिए बिना लेने के लिए धन्यवाद।

+1

FYI करें, इसके बारे में मुख्य कीवर्ड covariance, contravariance और invariance हैं। हां, जब आप इसके बारे में नहीं जानते हैं तो यह खोजना मुश्किल है। – delnan

+2

आपको 'IList ' लागू करना चाहिए। – SLaks

+0

नेट में सार्वजनिक सदस्य नाम ऊपरी कैमेलकेस होना चाहिए। एक बेहतर डिजाइन का सुझाव देने के लिए – SLaks

उत्तर

8

आप covariance उपयोग करने के लिए कोशिश कर रहे हैं।
नेट केवल इंटरफेस पर जेनेरिक भिन्नता का समर्थन करता है, जिससे यह काम नहीं करेगा।

इसके अलावा, सहप्रसरण केवल भावना अपरिवर्तनीय प्रकार पर बनाता है।
था यह संभव हो गया एक एक MyList<Fruit> को MyList<Apple> कन्वर्ट करने के लिए, तो आप सूची में एक Orange जोड़ने के लिए, टाइप सुरक्षा का उल्लंघन करने में सक्षम होगा।

इसके बजाय, आप विधि सामान्य बना सकते हैं:

public void Add<U>(IList<U> list) where U : T 
3

मुझे लगता है कि IMyList इंटरफेस के डिजाइन किया जाना चाहिए:

public interface IMyList<T> : IEnumerable<T> 
{ 
    void Add(T item); 
    void AddRange(IEnumerable<T> itemList); 
} 

सब कुछ उम्मीद के रूप में काम करता है। क्यूं कर? सिर्फ इसलिए कि .NET में 4.0 IEnumerable इंटरफ़ेस के प्रकार पैरामीटर टी में covariant है, यह क्या परिभाषा लग रहा है जैसे:

public interface IEnumerable<out T> : IEnumerable 

IMyList इंटरफेस (सूची डेकोरेटर) की सरल कार्यान्वयन:

public class MyList<T> : IMyList<T> 
{ 
    private readonly List<T> _list = new List<T>(); 

    #region Implementation of IMyList<in T> 

    public void Add(T item) 
    { 
     Console.WriteLine("Adding an item: {0}", item); 
     _list.Add(item); 
    } 

    public void AddRange(IEnumerable<T> itemList) 
    { 
     Console.WriteLine("Adding items!"); 
     _list.AddRange(itemList); 
    } 

    #endregion 

    #region Implementation of IEnumerable 

    public IEnumerator<T> GetEnumerator() 
    { 
     return _list.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

    #endregion 
} 
+0

+1 – phoog

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