2012-02-01 4 views
8

linq-to-objectsの派生型に基づいてオブジェクトをフィルタリングするにはどうすればよいですか?linqを使用したIEnumerableタイプの除外

私は最高のパフォーマンスで解決策を探しています。

使用されるクラス:

abstract class Animal { } 
class Dog : Animal { } 
class Cat : Animal { } 
class Duck : Animal { } 
class MadDuck : Duck { } 

私は三つの方法を知っている:、isキーワードを使用Exceptメソッドを使用して、OfTypeメソッドを使用します。

List<Animal> animals = new List<Animal> 
{ 
    new Cat(), 
    new Dog(), 
    new Duck(), 
    new MadDuck(), 
}; 

// Get all animals except ducks (and or their derived types) 
var a = animals.Where(animal => (animal is Duck == false)); 
var b = animals.Except((IEnumerable<Animal>)animals.OfType<Duck>()); 

// Other suggestions 
var c = animals.Where(animal => animal.GetType() != typeof(Duck)) 

// Accepted solution 
var d = animals.Where(animal => !(animal is Duck)); 
+2

'Duck'を継承する' MadDuck'があればどうでしょうか?返されるべきかどうか?そして、btw、あなたは何を達成しようとしていますか? 'is'とランタイム型チェックの使用は設計上の問題を示しているかもしれません。 – Groo

+0

良い質問があります。この特定のケースでは、私はDuckのサブクラスも除外したいと思います。それは、型を比較す​​るが、継承を比較しないので、私のオプション 'b'を無効にします。 – Aphelion

+0

私の2番目の質問について:OOPの観点からは、コードの他の部分は通常、実際のオブジェクトの種類に関係するべきではありません。その人は「可能な限り」知っていなければなりません。だから私はなぜあなたがこれをやっているのだろうかと思います。 – Groo

答えて

9

あなたも除外したい場合ダックのサブクラスでは、isが最適です。あなただけの.Where(animal => !(animal is Duck));

そうでない場合、メソッドGetTypeのSLLの勧告は

+0

サブクラスを除外したいので、これは簡潔でわかりやすい表記で、私はあなたの答えを受け入れました。 – Aphelion

+0

私はOfType ()を打ち負かすとは思わない。 – Will

4
  • Except()を使用したソリューションは、かなり重いです。
  • ソリューションisがあることに留意してください - Duck

    class SomeDuck : Duck 
    ... 
    // duck is Duck == true 
    var duck = new SomeDuck(); 
    

から他のソリューションを継承し、いくつかのSomeDuckクラスができたとしてもtrueを返します:

animals.Where(animal => animal.GetType() != typeof(Duck)) 
+1

ありがとうございます。あなたの提案を質問に含めました。 – Aphelion

1

あなたはDuckDuckのいずれかのサブクラスをしたくない場合は、返されるのが最善であるために、コードを短縮することができ、あなたはIsAssignableFromメソッドを使用する必要があります。

animals.Where(animal => !animal.GetType().IsAssignableFrom(typeof(Duck))); 
+0

ニース。私は以前に 'IsAssignableFrom'を使用していません。パフォーマンスはこの方法のためだと思います。いくつかのプロファイリングの良いケースのように聞こえる。 – Aphelion

+0

私はそれが 'as'キャストとヌルチェックのように速いと期待しています。 –

関連する問題