linq

2012-02-01 13 views
8

के साथ IENumerable प्रकारों को बाहर निकालें, मैं अपने व्युत्पन्न प्रकार के आधार पर वस्तुओं को फ़िल्टर-टू-ऑब्जेक्ट्स के साथ कैसे फ़िल्टर कर सकता हूं?linq

मैं सर्वोत्तम प्रदर्शन के साथ समाधान की तलाश में हूं।

इस्तेमाल किया कक्षाओं:

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

क्या होगा यदि आपके पास 'मैड डक' है, जो 'डक' से प्राप्त होता है? क्या उसे वापस किया जाना चाहिए या नहीं? और, बीटीडब्ल्यू, आप क्या हासिल करने की कोशिश कर रहे हैं? 'Is' और रनटाइम प्रकार-जांच का उपयोग डिज़ाइन समस्याओं को इंगित कर सकता है। – Groo

+0

अच्छा सवाल। इस विशिष्ट मामले में मैं डक के उप-वर्गों को भी बाहर रखा जाना चाहूंगा। इससे मेरा विकल्प 'बी' अमान्य हो जाएगा क्योंकि वे प्रकार की तुलना करते हैं लेकिन विरासत नहीं। – Aphelion

+0

मेरे दूसरे questioin के बारे में: एक ओओपी दृष्टिकोण से, आपके कोड के अन्य हिस्सों को आमतौर पर आपकी वस्तुओं के वास्तविक प्रकार से संबंधित नहीं होना चाहिए। "जितना संभव हो उतना छोटा" पता होना चाहिए। यही कारण है कि मुझे आश्चर्य है कि आप ऐसा क्यों कर रहे हैं। – Groo

उत्तर

9

आप भी निकालना चाहते हैं बतख के उप-वर्ग, फिर is सबसे अच्छा है। आप कोड को छोटा कर सकते करने के लिए सिर्फ .Where(animal => !(animal is Duck));

अन्यथा, GetType की SLL की सिफारिश सबसे अच्छा

+0

जैसा कि मैं उप-वर्गों को बाहर करना चाहता हूं और यह एक छोटा और अधिक पठनीय नोटेशन है, मैंने आपका जवाब स्वीकार कर लिया है। – Aphelion

+0

मुझे विश्वास नहीं है कि यह बीट्स ()। – Will

4
  • Except() का उपयोग कर समाधान काफी भारी है।
  • ध्यान रखें कि समाधान is - सच वापसी होगी यहां तक ​​कि कुछ SomeDuck वर्ग Duck

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

से विरासत में मिली एक अन्य समाधान हो सकता है:

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

धन्यवाद। मैंने प्रश्न में आपका सुझाव शामिल किया है। – Aphelion

1

आप Duck है और न ही Duck में से किसी उपवर्ग नहीं करना चाहते हैं लौटा दी है, तो आप IsAssignableFrom विधि का उपयोग करने की जरूरत है:

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

अच्छा। मैंने पहले कभी 'IsAssignableFrom' का उपयोग नहीं किया है। मुझे आश्चर्य है कि प्रदर्शन इस विधि के लिए है। कुछ प्रोफाइलिंग के लिए एक अच्छा मामला लगता है। – Aphelion

+0

मैं उम्मीद करता हूं कि यह 'as' cast के रूप में तेज़ हो जाए, फिर शून्य जांच करें। –

3

Difference between OfType<>() and checking type in Where() extension के अनुसार OfType कॉल, अपने विकल्प (क) के बराबर है साथ यद्यपि == सच बतख है, इसलिए कि मैं कहूंगा कि के आधार पर विकल्प के लिए छड़ी (क)।

संबंधित मुद्दे