2011-10-06 2 views
1

私はいくつかの子タイプを持つNodeUpgradeという基本クラスを持っています。特定の子クラスの例はFactoryUpgradeです。LINQを使用して一般的なリスト内の要素を選択し、特定の型にキャスト

私はNodeUpgradesのリストを持っています。これは、さまざまな子タイプを組み合わせたものです。どのようにしてNodeUpgradeの型を取得し、その特定の型にキャストするためのlinqクエリを記述しますか?

var allFactories = (from Node n in assets.Nodes 
        from FactoryUpgrade u in n.NodeUpgrades 
        where u.ClassID == NodeUpgradeTypes.Factory 
        select u) 

これ、もちろん、動作しません:

私の作業クエリは次のようになります。出力の最終的なタイプを指定することはできますか?

+0

は正しい構文ですか?あなたは何ですか? –

+0

ありがとう、私は変数名を忘れました。 – Extrakun

答えて

4

メソッドを使用することができます。リストに複数のタイプがあり、そのうちの1つだけが必要な場合は、OfType<T>()を使用してシーケンスをフィルタリングできます。

List<Animal> animals = ... 

// assumes all animals are cats 
var cats = animals.Cast<Cat>(); 
// var cats = (from animal in animals where ... select animal).Cast<Cat>(); 

// or maybe animals can contain dogs, but you don't want them 
var cats = animals.OfType<Cat>(); 

違いはOfTypeが実際に変換を試みる前に型チェックが実行されます一方、動物は、猫ない場合Castが例外をスローしますということです。あなたがユニフォームタイプを確信している場合、私はCastOfTypeより好むでしょう。

それぞれの場合に得られた配列は、IEnumerable<Cat>となり、その(またこれらは、ユーザー定義の変換を実行しないこと。あなたは、暗黙的または明示的な変換を定義した場合、それらは、これらの方法でサポートされません。注意してください)

1

あなたはシーケンスのすべての種類が指定されたタイプであることが確実な場合、あなたはCast<T>()拡張メソッドを使用することができますOfType<>

var allFactories = (from Node n in assets.Nodes 
        from FactoryUpgrade in n.NodeUpgrades 
        where u.ClassID == NodeUpgradeTypes.Factory 
        select u).OfType<ChildType>(); 
1

他の人からも言われているように、.OfType拡張メソッドを使用して型をフィルタリングします(継承モデルと適切なディスクリミネータを設定していると仮定します)。あなたのデータソース)。これにより、データベースでは、Discriminator(ClassID)に適切なWhere句が含まれます。

var allFactories = from n in assets.Nodes 
        from u in n.NodeUpgrades.OfType<FactoryUpgrade>() 
        select u; 

この場合、EF、LINQ to SQL、またはLinq to Objectsを使用している場合は、ここでは指定していません。それぞれには相続をモデリングする異なる方法があります。モデリング部分のヘルプが必要な場合は、使用しているOR/Mをお知らせください。

関連する問題