C# Linq `List<Interface>.AddRange` 메서드가 작동하지 않습니다.
문제
아래와 같이 정의된 인터페이스가 있습니다.
public interface TestInterface{
int id { get; set; }
}
그리고 해당 인터페이스를 구현하는 두 개의 Linq-to-SQL 클래스는 다음과 같습니다.
public class tblTestA : TestInterface{
public int id { get; set; }
}
public class tblTestB : TestInterface{
public int id { get; set; }
}
tblTestA 및 tblTestB의 데이터베이스 레코드로 채워진 IEnumerable 목록 a 및 b가 있습니다.
IEnumerable<tblTestA> a = db.tblTestAs.AsEnumerable();
IEnumerable<tblTestB> b = db.tblTestBs.AsEnumerable();
그러나 다음은 허용되지 않습니다.
List<TestInterface> list = new List<TestInterface>();
list.AddRange(a);
list.AddRange(b);
다음과 같이 해야 합니다.
foreach(tblTestA item in a)
list.Add(item)
foreach(tblTestB item in b)
list.Add(item)
내가 잘못하고 있는 것이 있나요?어떤 도움을 주셔서 감사합니다
해결책
IEnumerable<tblTestA>
에서 IEnumerable<TestInterface>
로 변환이 있습니다.
기능은 V2에서 CLR에 있었지만 C # 4에만 노출되었습니다 (그리고 프레임 워크 유형은 .NET 4 이전에이를 활용하지 않았습니다). 만 은 일반적인 인터페이스 및 대리인 (클래스가 아님)에만 적용되며 참조 유형에만 적용됩니다 (예 : IEnumerable<int>
에서 IEnumerable<object>
에서 IEnumerable<T>
로의 변환이 없습니다. 오브젝트는 API의 "out"만 있지만, IList<T>
는 해당 API와 함께 값을 추가 할 수 있기 때문에 불변 입니다.
일반적인 상반기도 지원되어 다른 방향으로 작동합니다. 예를 들어 IComparer<object>
에서 IComparer<string>
로 변환 할 수 있습니다.
C # 4를 사용하지 않으면 TIM의 Enumerable.Cast<T>
를 사용하는 TIM의 제안은 좋은 것입니다 - 당신은 약간의 효율을 잃지 만 작동합니다.
일반적인 분산에 대해 자세히 알고 싶다면 Eric Lippert는 NDC 비디오 페이지 .
다른 팁
당신은 아무것도 하지 않고 잘못된: List<TestInterface>.AddRange
기대하는 IEnumerable<TestInterface>
.그것을 받아들이지 않을 것인 IEnumerable<tblTestA>
나 IEnumerable<tblTestB>
.
귀하의 foreach
루프를 작동합니다.또는 사용할 수 있습니다 Cast
을 변경하는 유형:
List<TestInterface> list = new List<TestInterface>();
list.AddRange(a.Cast<TestInterface>());
list.AddRange(b.Cast<TestInterface>());
addRange는 인터페이스 개체 목록을 기대하고 "a"와 "b"varaibles는 파생 클래스 객체 목록으로 정의됩니다.분명히 .NET은 논리적으로 인터페이스를 구현하기 때문에 인터페이스 객체 목록으로 점프하고 대우 할 수 있으므로 논리가 3.5에서 .NET로 빌드되지 않기 때문에 인터페이스 객체 목록으로 점프하고 대우 할 수 있습니다.
그러나이 능력 ( "공분산"이라고 함)은 .NET 4.0에 추가되었지만, 그로 인해 업그레이드 할 때까지 루핑을 통해 멈추거나 toarray ()를 호출 한 다음 결과를TaskInterface [] 또는 Adere Linq 쿼리가 각 항목을 대소 문자로 만들고 새 목록을 만듭니다.
a
그리고 b
유형이다 IEnumerable<tblTestA>
그리고 IEnumerable<tblTestB>
하는 동안 list.AddRange
매개변수는 유형이어야 합니다. IEnumerable<TestInterface>