문제

이 두 수업이있는 경우 :

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>

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top