2009-05-04 2 views
1

와 서브 클래스의 컬렉션을 추가 > .AddRange (목록 <B>)하지만 컴파일러는 거부 :는 AddRange

Argument '1': cannot convert from 'System.Collections.Generic.List<A>' 
to 'System.Collections.Generic.IEnumerable<B> 

나는 완전히 이해하는 IEnumerable을 < 때문에 B >은 IEnumerable <A>에서 상속하지 않으며 해당 제네릭 형식에는 상속이 있습니다. 목록 < > .Add (A 항목) B 항목에서 작동하기 때문에

내 솔루션 목록 <B>을 통해 열거하고 개별적으로 항목을 추가하는 것입니다

foreach(B item in listOfBItems) 
{ 
    listOfAItems.Add(item); 
} 

은 그러나, 오히려 비 표현 왜냐하면 내가 원하는 것은 AddRange 뿐이다.

나는

List<B>.ConvertAll<A>(delegate(B item) {return (A)item;}); 

를 사용할 수 있지만 불필요하게 복잡한 그리고 내가 변환 아니에요 때문에 잘못된, 내가 캐스팅하고 있습니다.

질문 : 나는 나를 <를 나열하는 유사 한 라이너로 A의 모음으로 B의 컬렉션을 복사 할 수 것이라고 여기에 추가 할 것입니다 무슨 방법 내 자신의 목록과 같은 모음을 작성한다면 A > .AddRange (목록 <B>) 은 최대 유형 안전을 유지합니다. (그리고 최대로 나는 인수가 콜렉션과 유형 상속 검사라는 것을 의미합니다.)

답변

1

.net의 제네릭이 공분산을 지원하지 않기 때문에 유감스럽게도 작동하지 않습니다.

그러나이 문제를 극복하기 위해 작은 도우미 메서드 나 클래스를 만들 수 있습니다.

당신이 당신의 자신의 목록 클래스를 구현하는 경우, 당신은 추가로 일반 매개 변수를 사용하여 공분산을 추가 할 수 있습니다

class MyList<T> { 
    void AddRange<U>(IEnumerable<U> items) where U: T { 
     foreach (U item in items) { 
      Add(item); 
     } 
    } 
} 
0

내가 가지고 올 수있는 유일한 것은이 일을 의미 호출이

public class MyList<T> : List<T> 
{ 
    public void AddRange<Tother>(IEnumerable<Tother> col) 
     where Tother: T 
    {  
     foreach (Tother item in col) 
     { 
      this.Add(item); 
     } 
    } 
} 

입니다 MyList <A> .AddRange <B> (MyList <B>). 인수가 열거 가능하지 않거나 유형 상속이 작동하지 않아 내 질문의 최대 유형 안전 요구 사항을 충족시키지 못하면 실패합니다.

+0

- 적어도 저에게는 기대되는 행동입니다. 당신은 무엇을 기대합니까, 아니면 어떻게 이것이 문제입니까? – Lucero

+0

정확히 내가 의심하는 바입니다. 나는 이것이 최대 타입 안전에 대한 나의 질문 요구 사항을 만족 시킨다는 것을 말하고 있었다. –

+0

또한 컴파일러가 형식이 호환된다는 것을 컴파일러가 알고 있기 때문에 (항목을 "편집"에 추가했는지 확실하지 않음) "항목"을 "T"로 변환해서는 안됩니다. – Lucero

1

당신은 할 수 없습니다 :

실제로
listOfAItems.AddRange(listOfBItems.Cast<A>()); 
+0

음, 목록이 없습니다 . 캐스트 () 메소드. –

+0

System.Linq를 참조하고 있습니까? .NET 2.0에 대해 실행중인 경우 Cast 이 Linq 확장 방법 중 하나이므로 사과드립니다. – BFree

+0

True로, .NET 버전 3.5 이상에서만 사용할 수 있습니다. 그러나 확장 메서드는 코드에서 "깨끗한"것이지만 항상 효율적이지는 않습니다. 이 경우 제네릭 매개 변수를 사용한 접근 방식이 자주 호출되는 경우 훨씬 빠릅니다. – Lucero

1

내가 LINQ 사용하여이를 달성 할 수 있었다 ...

listOfAItems.AddRange(listOfBItems.Cast<A>()); 
+1

여기에 질문/답변에 대한 자세한 내용을 보려면 http://stackoverflow.com/about을 읽어보십시오. 귀하의 기고가 질문에 답변하지 않습니다. ** BFree 응답 **에 대한 의견이 더 많습니다. ** 일단 평판을 높이면 추가 할 수 있습니다. http://stackoverflow.com/faq#reputation –

1

을 경우에는 어디 제네릭 형식이 상황에서 자신을 찾을 변형되지 않으며, 다음과 같은 확장 방법은 여러분의 인생을 더 쉽게 만들 수 있습니다

public static void AddRange<TList,TOther>(this List<TList> list, IEnumerable<TOther> collection) where TOther: TList { 
    foreach(TOther e in collection) { 
     list.Add(e); 
    } 
} 

을 대신 List<T>에서 파생하는 데 또는이에게 나를 필요없이 일부 유틸리티 클래스에서 thod를 사용하면 확장 메소드로 사용하면 사용이 간단 해집니다. 또한 추론에서 이익이 될 수 있으므로이 이전에 유효하지 않은 호출은 수정없이 유효 될 것이다 ". 인수가 열거되지 않은 경우 또는 유형 상속이 작동하지 않는 경우 실패"

List<Animal> animals; 
List<Dog> dogs; 
animals.AddRange(dogs);