2009-03-26 2 views
19

이 질문은 이전 질문에서 제기 된 내용을 다루지 만 확실히 찾을 수 없었습니다.기본 유형 목록을 상속 된 형식 목록으로 변환

기본 클래스의 일반 목록을 매개 변수로 사용하는 C# 클래스의 메서드가 있습니다. 상속 된 클래스의 목록을 전달해야하며이를 수행하는 방법을 정확하게 알지 못합니다. 내 시도에 오류가 있습니다. 다음은이를 보여주기위한 샘플 코드입니다.

public class A 
{ 
    public static void MethodC(List<A>) 
    { 
     // Do Something here with the list 
    } 
} 
public Class B : A 
{ 
    // B inherits from A, A is the Base Class 
} 

// Code utilizing the above method 
List<B> listOfB = new List<B>(); 
A.MethodC((List<A>) listOfB); // Error: this does not work 
A.MethodC(listOfB.ToList<typeof(A)>()); // Error: this does not work 
A.MethodC(listOfB.ConvertAll<A>(typeof(A))); // Error: this does not work 
// how can I accomplish this? It should be possible I would think 

참고 : 참고로 최종 작업 방법은 다음과 같습니다. 나는 나의 문제에 대한 더 나은 해결책을 가지고있다. 그러나 기술적 인면에서 나의 질문은 부적절하게 표현 된 것이기 때문에 그 질문에 대한 답이 아니었다.

public static DataTable 
    ObjectCollectionToDataTable<GLIST> 
     (List<GLIST> ObjectCollection) where GLIST 
       : BaseBusinessObject 
     { 
      DataTable ret = null; 

      if (ObjectCollection != null) 
      { 
       foreach (var b in ObjectCollection) 
       { 

        DataTable dt = b.ToDataTable(); 
        if (ret == null) 
         ret = dt.Clone(); 
        if (dt.Rows.Count > 0) 
         ret.Rows.Add(dt.Rows[0].ItemArray); 
       } 
      } 

      return ret; 
     } 
+0

그건 내가 너에게 준 같은 대답이야. –

+0

그리고 그것은 원래 당신이 물었던 것에 대한 답이기도하다. :) –

답변

29

사용 가능한 LINQ이 있다면 당신은 현재의 C# 버전의 공분산의 부족을 해결하고

var ListOfA = ListOfB.Cast<A>().ToList(); 
+0

나는 linq을 가지고 있다고 생각지 않지만, 어쨌든 효과가 있었다. 빠른 응답을 보내 주셔서 대단히 감사합니다. – stephenbayer

+0

가능한 문제점 - MethodC가 MethodC 외부에서 해당 변경 사항을 볼 수 있도록 목록을 수정해야합니까? –

+0

다행입니다!LINQ 확장 메서드를 사용할 수 있다고 생각하는 유일한 이유는 예제에서 ToList를 사용했기 때문입니다. –

9

당신은 그렇게 할 수 없습니다. 허용되지 않는 이유를 이해하려면 List<Base>으로 캐스팅 된 후 AddList<Derived>에서 호출 된 경우 어떻게 될지 상상해보십시오.

또한 C# 4.0이 다르다는 대답은 잘못되었습니다. 목록을 수정하지 않아도됩니다. IEnumerable 만 가능합니다. 컬렉션에 항목을 추가 할 수 없기 때문입니다.

업데이트 : 당신이 더 이상 같은 목록을 통과하지 않아서 당신이 떠난 솔루션에서 작동하는 이유입니다. 원본의 복사본 인 완전히 새로운 목록을 만들고 있습니다. 이것이 내가 목록을 수정하는 것에 대해 묻는 이유입니다. MethodC이 목록의 항목 수를 변경하면 원래 목록이 아닌 사본이 변경됩니다.

나는 다음과 같이 당신을위한 이상적인 솔루션이라고 생각 :

public abstract class A 
{ 
    public void MethodC<TItem>(List<TItem> list) where TItem : A 
    { 
     foreach (var item in list) 
      item.CanBeCalled(); 
    } 

    public abstract void CanBeCalled(); 
} 

public class B : A 
{ 
    public override void CanBeCalled() 
    { 
     Console.WriteLine("Calling into B"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<B> listOfB = new List<B>(); 

     A a = new B(); 

     a.MethodC(listOfB); 
    } 
} 

공지 사항이 솔루션과 함께, 당신이 처음에 이상한 변환을 수행 할 필요없이 MethodC에 직접 List<B>을 통과 할 수있는 방법. 따라서 불필요한 복사 작업이 필요 없습니다.

A의 목록이어야한다고 주장하는 대신 A에서 파생 된 모든 항목의 목록을 MethodC에 허용했기 때문에이 방법이 유용합니다.

+0

나는 그것이 사실이라고 생각하지 않는다, 그것은 잘 동작한다. 내 메서드 호출은 컬렉션을 통해 루프를 작동하고 추상 (재정의) 메서드 및 속성에 따라 작동합니다. 위의 코드를 이전 응답에서 사용했는데 잘 작동합니다. 프로젝트는 컴파일러로 CSC.exe (C#) 3.0이있는 .NET 2.0입니다. – stephenbayer

+0

위 업데이트를 참조하십시오. –

+0

이 작업을 수행하는 데 어려움을 겪고 계신 것 같습니까? :) –

3

다음은 잘못된 유형의 목록에있는 개체를 제외하는 대답입니다. 이것은 내 의견으로는 훨씬 안전한 방법입니다 :

List<A> ListOfA = ListOfB.OfType<A>().ToList(); 

OfType 메서드는 Cast가 오류를 던질 때 잘못된 파생 클래스의 항목을 제외합니다.

관련 문제