AddRange와 함께 서브 클래스 모음을 추가합니다
-
03-07-2019 - |
문제
이 두 수업이있는 경우 :
class A {}
class B : A {}
목록 u003CA>을 만들지 만 목록 u003CB>을 호출하여 목록을 추가하고 u003CA>u003CB>싶지만 컴파일러는 다음을 거부합니다.u003C/b>u003C/a>u003C/b>u003C/a>
Argument '1': cannot convert from 'System.Collections.Generic.List<A>'
to 'System.Collections.Generic.IEnumerable<B>
ienumerable u003CB>이 ienumerable에서 물려받지 않기 때문에 완전히 이해 u003CA>하고 있습니다. 일반적인 유형은 상속을 가지고 있습니다.u003C/a>u003C/b>
내 솔루션은 목록을 통해 열거 u003CB>하고 개별적으로 항목을 추가하는 것입니다. 목록 u003CA>.add (항목)는 B 항목과 함께 작동합니다.u003C/a>u003C/b>
foreach(B item in listOfBItems)
{
listOfAItems.Add(item);
}
그러나 제가 원하는 것은 단지 AddRange이기 때문에 다소 표현력이 없습니다.
나는 사용할 수있다
List<B>.ConvertAll<A>(delegate(B item) {return (A)item;});
그러나 그것은 불필요하게 복잡하고 변환하지 않기 때문에 캐스팅하고 있기 때문에 불필요하게 복잡하고 잘못된 이름입니다.
의문: 내가 나만의 u003CA>u003CB>목록u003C/b>u003C/a> 과 같은 컬렉션을 작성한다면 B를 컬렉션에 복사 할 수있는 방법을 추가 할 수있는 방법. 그리고 최대 유형 안전성을 유지합니다. (그리고 최대로 나는 논쟁이 수집 및 유형 억제 점검임을 의미합니다.)
해결책
실제로, 일반 유형은 현재 변형이 아닙니다. C# 4.0에서 ienumerable<B
> ienumerable로 전환 할 수 있습니다<A
> B를 통해 A로 전환 할 수있는 경우 참조 변환. 이 기능의 디자인에 대한 자세한 내용은 다음을 참조하십시오.
http://blogs.msdn.com/ericlippert/archive/tags/covariance+and+contravariance/default.aspx
다른 팁
.NET의 제네릭은 (아직) 공분산을 지원하지 않기 때문에 이것은 불편하게 작동하지 않습니다.
그러나이 문제를 극복하기 위해 작은 도우미 방법이나 클래스를 만들 수 있습니다.
자신의 목록 클래스를 구현하는 경우 추가 일반 매개 변수를 사용하여 공분산을 추가 할 수 있습니다.
class MyList<T> {
void AddRange<U>(IEnumerable<U> items) where U: T {
foreach (U item in items) {
Add(item);
}
}
}
그냥 할 수 없어요 :
listOfAItems.AddRange(listOfBItems.Cast<A>());
나는 linq를 사용하여 이것을 달성 할 수 있었다 ...
listOfAItems.AddRange(listOfBItems.Cast<A>());
일반적인 유형이 변형되지 않는 상황에 처한 경우 다음 확장 방법이 삶을 더 쉽게 만들 수 있습니다.
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>
또는 일부 유틸리티 클래스 에서이 방법을 사용하면 확장 방법으로 사용하면 사용법을 단순화합니다. 또한 추론으로 이익을 얻을 수 있으므로 이전에 유효하지 않은 호출은 수정없이 유효합니다.
List<Animal> animals;
List<Dog> dogs;
animals.AddRange(dogs);
내가 생각해 낼 수있는 유일한 것은 이것입니다
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 u003CA>.addrange u003CB>(mylist u003CB>)를하는 것을 의미합니다. 인수를 열거 할 수 없거나 유형 상속이 작동하지 않으면 내 질문의 최대 유형 안전 요구 사항을 충족시키는 경우 실패합니다.u003C/b>u003C/b>u003C/a>