2009-07-13 3 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() { } 
} 

私は基本的にタイプ一覧であり、私の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がスローされると記載されています。参照変換は、ある参照型から別の参照型への変換です。参照のタイプを変更する可能性はありますが、コンバージョンのターゲットのタイプや値は決して変更しません。オブジェクトの型をある型から別の型にキャストすることは、この例外の原因になることがよくあります。

ListがMachineProductCollectionのベースであることを考慮すると、これは本当にInvalidCastExceptionであるべきですか?

答えて

5

はい、無効なキャスト例外が正しくあります。派生クラスから基本クラスに自由にキャストできますが、派生クラスのインスタンスであるでない限り、基本クラスから派生クラスにキャストできません。これはあなたがこれを行うことができない同じ理由です:

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

右か? objectstringのベースで、objectからstringに自由にキャストすることはできません。

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

偉大な答え - 短いと甘い。これは、オブジェクト/文字列の類推によって特に完全に理解されます。ありがとう。 –

1

List<MachineProduct>が逆は明らかに真実であっても、必ずしもMachineProductCollectionではありませんので、あなたがInvalidCastExceptionを取得している:objは確かに文字列であるため、一方で、これは動作します。

実際MachineProductCollectionList<T>のシーケンスコンストラクタを使用することであろう戻るための最も簡単な解決策:あなたは私は経由して(あなたがLINQへのアクセス権を持って推測しているラムダ式を使用していることから、しかし

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

    return new MachineProductCollection(found); 
} 

を。

言っ
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すべての詳細と正解。申し訳ありませんが、私は2つの答えを正しいとマークできませんでした。 –

関連する問題