2012-01-26 21 views
10

Sorunumun nasıl çağrıldığını bilmediğimden, kimsenin aynı soruyu yakın zamanda ya da hiç istemediğini garanti edemem.Generics ve Inheritance hakkında (kötü başlığımı affet)

Fark ettim ki, benzer bir başlığa sahip birkaç konu var, ancak benim sorunumla alakalı görünmüyorlar.

Generics'i uygulayan özel bir liste sınıfım var.

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 */ } 
} 

Ben de sınıfları:

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 bir MyList olmasına rağmen (ki:

class Apple : Fruit 

ve Şimdi

class Banana : Fruit 

, ilgili kod geliyor Apple) ve Apple Meyve, VisualStudio kabul etmiyor MyList (Of Fruit) sorgusu sorulduğunda MyList (Of Apple) argüman olarak. Böyle listeyi ilan etmek olsaydı

Ancak:

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

Sonra her şey yeniden çalışır. Tam olarak ne yanlış yaptım?

Bir cevap çok takdir edilecek ve cevap vermeden bile okumaya zaman ayırdığınız için teşekkür ederiz.

+1

Bilginize, Bununla ilgili ana anahtar kelimeler kovaryans, kontrasepsiyon ve değişmezliktir. Evet, bunu bilmediğin zaman bulmak zor. – delnan

+2

IList 'öğesini uygulamanız gerekir. – SLaks

+0

.Net'deki genel üye adları UpperCamelCase olmalıdır. Daha iyi bir tasarım önermek için – SLaks

cevap

8

covariance'u kullanmaya çalışıyorsunuz.
.Net yalnızca arabirimlerde genel varyansı destekler, bu nedenle çalışmaz. Ayrıca kovaryans sadece değişmez tipler üzerinde anlamlıdır.
MyList<Apple> ürününü MyList<Fruit> numaralı telefona dönüştürmek mümkün olsaydı, listeye bir tür Orange ekleyebilirdiniz, bu da tür güvenliğinizi ihlal ediyor olabilir.

Bunun yerine, yöntem jenerik yapabilirsiniz:

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

Ben IMyList arayüzünün tasarım olması gerektiğini düşünüyorum: beklendiği gibi

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

Her şey çalışır. Niye ya? .NET 4.0 IEnumerable arayüzü tip parametresi T bildirdiğinden, sırf bu tanım göründüğünü gibi:

public interface IEnumerable<out T> : IEnumerable 
IMyList arayüzüne (Liste dekoratör) ait

Basit uygulanması:

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