2009-03-16 10 views
0

私はLabFileBaseという基本クラスを持っています。リストを作成し、派生クラスを追加しました。私は定義したキーに基づいて特定のオブジェクトのリストを検索したい。私が抱えている問題は、LINQ式でどのようにダウンキャストしているかです。ダウンキャスティングとLinq

ここではいくつかのサンプルコードです:

public abstract class LabFileBase 
{ 
} 

public class Sample1 : LabFileBase 
{  
    public string ID {get;set;} 
    public string Name {get;set;} 
    //.. 
} 

public class Sample2 : LabFileBase 
{  
    public string ID {get;set;} 
    public string Name {get;set;} 
    //.. 
} 

私は特定のサンプル2タイプを検索したいが、私は私はこのような通常のforeachループを使用した場合にダウンキャストする必要があります。

foreach(var s in processedFiles) //processedFiles is a List<LabFileBase> 
    if (s is Sample2) 
     var found = s as Sample2; 
      if (found.ID = ID && found.Name == "Thing I'm looking for") 
        //do extra work 

私は多くの場合、次のようなものがあります。

var result = processedFiles.Select(s => s.ID == SomeID && s.Name == SomeName); 

これは可能なのでしょうか、構文的な句読点他のオブジェクトのために私の唯一のオプションであるforeachです。 Sample1とSample2のIDと名前は同じフィールドのみです。

編集:ご協力いただきありがとうございます。私は実装するためにバックログにほとんどすべてを入力しました。

答えて

5

をJonの答えに詳述すると、OfTypeはあなたのベースにこれらのフィールドを置くことを望んでいない場合は、ほぼ確実に正しい演算子でありますクラス。例:

foreach(var s in processedFiles.OfType<Sample2>()) 
    if(s.ID == ID && s.Name == "Thing I'm looking for") 
     // whatever 

foreach(var s in processedFiles.OfType<Sample1>()) 
    if(s.ID == ID && s.Name == "Some other thing") 
     // and so on 
6

IDNameをベースクラスに入れないのはなぜですか?それからダウンキャストは必要ありません。

の場合にキャストが必要な場合は、CastOfTypeの演算子が役立ちます。それぞれは、シーケンスを指定されたタイプのシーケンスに変換します。Castは、各要素の正しいタイプであると仮定します(そうでない場合は例外をスローします)。 OfTypeは、C#as演算子のように機能し、正しい型になり、他の要素を無視する要素のみを返します。

+0

seq.OfType ()は、seq.Where(el => elはMyFavType)のように機能します。 – yfeldblum

+0

@ジョン:私は間違いなくIDと名前をベースクラスに移すことを考えます。私はそれについてもっと考えると、彼らは本当にそこに属しています。 – Chris

+0

@ジャスティス:それは*でも*ターゲットタイプのシーケンスで終わっているからです。それはseq.Whereのようなものです。(...)キャスト<...>() –

0

興味深い質問です。 Jon Skeet(このオプションよりも優れています)に加えて、より手作業の代替手段を試すことができます。それがあるオブジェクトの型の識別子を含む追加のプロパティを追加します。

public abstract class LabFileBase 
{ 
    public string LabFileObjectType { get; } 
    public string ID {get;set;} 
    public string Name {get;set;} 
} 


public class Sample1 : LabFileBase 
{  
    public string LabFileObjectType { get { return "Sample1"; } } 
    //.. 
} 

public class Sample2 : LabFileBase 
{  
    public string LabFileObjectType { get { return "Sample2"; } } 
    //.. 
} 

その後、あなたにもそのプロパティに対してクエリができます

var result = processedFiles.Select(s => s.ID == SomeID && s.Name == SomeName && s.LabFileObjectType == "Sample2"); 
+0

あなたがコードでテストをしたいのであれば、なぜ "&& s Sample1"を使ってみませんか? –

+0

あなたはおそらくそうでしょう。私はあなたの事例から代替案があると言っています。それは間違いなくより適切です。 –