2012-01-26 2 views
10

내 문제가 어떻게 불려지는지 모르겠으므로 아무도 같은 질문을 최근에 또는 전혀 요구하지 않았다는 것을 보장 할 수는 없습니다.Generics and Inheritance (나의 나쁜 제목을 용서하십시오)

비슷한 제목의 스레드가 꽤 있지만, 내 문제와 관련이없는 것 같았습니다.

제네릭을 구현하는 사용자 지정 목록 클래스가 있습니다.

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 

를, 관련 코드를 제공 애플)과 애플은 과일입니다, VisualStudio는 accep하지 않습니다 MyList (Of Apple)를 인수로 사용하면 MyList (Of Fruit)에 질문합니다. 나는이 같은 목록을 선언한다면

그러나 :

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

그런 다음 모든 것을 다시 작동합니다. 정확히 내가 뭘 잘못 했니?

답변을 많이 주시면 감사하겠습니다. 답장을하지 않고도 시간을내어 읽어 주셔서 감사합니다.

+1

참고는 이것에 관한 주요 키워드는 공분산, 반항 및 불변이다. 예, 당신이 그것에 대해 모를 때 찾기가 다소 어렵습니다. – delnan

+2

'IList '을 구현해야합니다. – SLaks

+0

.Net의 공용 멤버 이름은 UpperCamelCase 여야합니다. – SLaks

답변

8

covariance을 사용하려고합니다.
.Net 인터페이스의 일반 분산 만 지원하므로 작동하지 않습니다.

또한 공분산은 변경 불가능한 유형에만 적용됩니다.
MyList<Fruit>으로 변환 할 수 있다면 목록에 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 인터페이스는 그것의 유형 매개 변수 T의 공변이다해서,이 정의는 모습입니다 같은 :

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