2009-07-13 4 views
1

다음 코드는 InvalidCastException을 발생시킵니다.C# InvalidCastException 같음 기본 클래스

public static MachineProductCollection MachineProductsForMachine(
    MachineProductCollection MachineProductList, int MachineID) 
{ 
    return (MachineProductCollection) 
     MachineProductList.FindAll(c => c.MachineID == MachineID); 
} 

MachineProductCollection이 findall은()가 반환해야 정확히 무엇 MachineProducts의 일반적인 목록은 단지이기 때문에이 나를 ​​놀라게한다. 다음은 MachineProductCollection의 전체 소스 코드입니다. 주목할 것은 List에 대한 래퍼 일뿐입니다.

[Serializable] 
public partial class MachineProductCollection : 
     List<MachineProduct> 
{ 
    public MachineProductCollection() { } 
} 

나는 기본적으로 List 형태이며 내 MachineProductCollection에 각 항목을 추가 findall은() 결과를 통해 루프 다음에 의지. 분명히, 나는 필요한 반복을 좋아하지 않는다.

public static MachineProductCollection 
    MachineProductForMachine(MachineProductCollection 
    MachineProductList, int MachineID) 
{ 
    MachineProductCollection result = 
     new MachineProductCollection(); 


    foreach (MachineProduct machineProduct in 
     MachineProductList.FindAll(c => c.MachineID == MachineID)) 
    { 
     result.Add(machineProduct); 
    } 

    return result; 
} 

설명서에는 명시 적 참조 변환 중에 오류가 발생하면 InvalidCastException이 throw됩니다. 참조 변환은 하나의 참조 유형에서 다른 참조 유형으로의 변환입니다. 참조 유형을 변경할 수는 있지만 전환 목표의 유형이나 값은 절대 변경하지 않습니다. 한 유형에서 다른 유형으로 객체를 형변환하는 것은이 예외의 빈번한 원인입니다.

List가 MachineProductCollection의 기반임을 고려해 볼 때 실제로이 값이 InvalidCastException이되어야합니까?

답변

5

예, 잘못된 캐스트 예외가 있습니다. 파생 클래스에서 기본 클래스로 자유롭게 캐스트 할 수 있지만 실제로 이 파생 클래스의 인스턴스 인 인 경우를 제외하고는 기본 클래스에서 파생 클래스로 맹목적으로 캐스트 할 수 없습니다. 이 작업을 수행 할 수없는 이유는 다음과 같습니다.

object obj = new object(); 
string str = (string) obj; 

오른쪽? object은 의베이스이며 object에서 string까지 자유롭게 캐스트 할 수 없습니다.

object obj = "foo"; 
string str = (string) obj; 
+0

위대한 답변 - 짧고 달콤한. 특히 객체/문자열 유추를 통해 이제는 완전히 이해가됩니다. 감사. –

1

List<MachineProduct>이 역은 분명히 사실에도 불구하고, 반드시 MachineProductCollection되지 않습니다 InvalidCastException 때문에이 있어요 :이 obj 이후 일 것입니다 반면에 실제로 문자열입니다. 당신이 (를 통해 당신이 LINQ에 액세스 할 수 같은데요 람다 표현식을 사용하고 있기 때문에,

public static MachineProductCollection 
    MachineProductForMachine(MachineProductCollection MachineProductList, int MachineID) 
{ 
    List<MachineProduct> found = 
     MachineProductList.FindAll(c => c.MachineID == MachineID)) 

    return new MachineProductCollection(found); 
} 

그러나 :

실제 MachineProductCollection이 될 것 반환하는 가장 간단한 솔루션

List<T>의 시퀀스 생성자를 사용합니다.

말했다
public static MachineProductCollection 
    MachineProductForMachine(MachineProductCollection MachineProductList, int MachineID) 
{ 
    IEnumerable<MachineProduct> found = 
     MachineProductList.Where(c => c.MachineID == MachineID)) 

    return new MachineProductCollection(found); 
} 

, 당신은 단지 IEnumerable<MachineProduct>를 반환보다는 더 나을 수 있습니다) 3.5 NET 또는 LINQ Bridge, 이는 당신이 중간 목록을 건너 뛰도록 Where 확장 방법을 사용할 수 있다는 것을 의미 자신의 컬렉션 유형을 생성합니다. 이것은 아마도 MachineProductCollection에 특별한 논리를 추가 할 계획이 아니면 않는 한 당신의 인생을 더 쉽게 만들 것입니다. 이 경우 로직을 제공하기 위해 항상 IEnumerable<MachineProduct>에 대한 확장 메소드를 작성할 수 있습니다. 고려해야 할 몇 가지 사항 ...

+0

+1 모든 세부 사항 및 정답. 죄송합니다. 나는 두 개의 답을 옳다고 표시 할 수 없습니다. –

관련 문제