2011-05-19 20 views
5

मेरी व्यक्तिगत कोडिंग शैली Enumerable.OfType<T>() से संबंधित है। मैं हर जगह इसका उपयोग करता हूं, यह थोड़ा सा समझ में आता है। विशेष रूप से IEnumerable<T> शक्तिशाली linqToObject कार्यक्षमता की अनुमति देता है। मुझे ऑब्जेक्ट कोलेक्शन जैसे "प्रकार-असुरक्षित" लूपिंग से नफरत है जैसे नीचे नमूने। अब मेरे पास इन "UnGenericCollections" में लूपिंग के बारे में कुछ प्रश्न हैं।सी #, objectCollection.OfType <T>() और foreach (ऑब्जेक्ट कोलेक्शन में टी आइटम), IENumerable <T>

प्रश्न 1: यदि मैं इस ArrayList से Enumerable<T> को सरल फ़ोरैच/if-check के साथ तुलना में अतिरिक्त लूप कितना बड़ा रूपांतरित करता हूं?

var ark = new ArrayList(); 
ark.Add(new Human()); 
ark.Add(new Human()); 
ark.Add(new Animal()); 

बजाय:

foreach (object passenger in ark) 
{ 
    if (passanger is Human) { } 
    if (passanger is Animal) { } 
} 

मैं का उपयोग करें:

foreach (var human in ark.OfType<Human>()) 
{ 
} 

foreach (var animal in ark.OfType<Animal>()) 
{ 
} 

प्रश्न 2: एक अलग टाइप चर, कास्टिंग के जो रास्ते में एक foreach पाश के दौरान/परिवर्तित हो जाएगा उपयोग किया गया? क्या यह एक भाषा सुविधा है या क्या यह बॉक्स से बाहर काम करता है?

foreach (Human human in ark) { } 

मेरी भयानक अंग्रेजी को धीरज रखने के लिए धन्यवाद। सादर, बेंजामिन

+1

संपादक नोट: भयानक अंग्रेजी को सही किया गया है। – Amy

उत्तर

2

उत्तर: 1:

अपने नमूने में - आप वास्तव में पूर्ण गणनीय से अधिक बार-बार दोहराना दो बार हो सकता है।

// i use 
foreach (var human in ark.OfType<Human>()) 
{ 
} 

foreach (var animal in ark.OfType<Animal>()) 
{ 
} 

उत्तर: 2:

यह अगर वहाँ संदूक में किसी भी गैर मानव हैं एक InvalidCastException अपवाद होगा।

मैं व्यक्तिगत रूप से ark.OfTypes<T>() पसंद करते हैं, इस मामले में मैं जानता हूँ कि मैं केवल Human और Animals से निपटने के लिए चाहते हैं, लेकिन Elves अनदेखी की जाएगी। इस तरह कोड बहुत अधिक क्लीनर है और आप अपने foreach पाश में दृढ़ता से टाइप की गई वस्तु से निपट रहे हैं।

लेकिन अगर मैं Elves को अनदेखा नहीं करना चाहता, तो मैं पूरी तरह से ArrayList के माध्यम से पुनरावृत्ति लेता हूं और कास्ट का उपयोग करता हूं।

+0

जेनेरिक आईनेमेरेबल < T > – benwasd

+1

@ben - अब आपके संपादन के साथ यह समझ में आता है। मैं जवाब अपडेट करूंगा। – YetAnotherUser

2

आपको कोई फर्क नहीं पड़ता क्योंकि ArrayList IENumerable लागू करता है। असल में, इस इंटरफ़ेस को लागू करने वाली किसी भी चीज़ को फ़ोरैच स्टेटमेंट में उपयोग किया जा सकता है।

एक var स्थापित करने के बजाय ऑब्जेक्ट को कास्ट करना (क्योंकि यह एक स्पष्ट कलाकार है) लेकिन यदि आपके पास गणना के अंदर एक जानवर है, तो आप कास्टिंग अपवादों से निपटने के लिए समाप्त हो जाएंगे।

foreach (Animal animal in ark) { } // this will blow up an exception if the object is Human 
0

Enumerable.OfType सभी तत्वों के ऊपर जाने के लिए और आप के लिए is T जांच करेंगे। तो संग्रह में सभी तत्वों पर हर OfType कॉल फिर से शुरू हो जाएगा। यह धीमा होना चाहिए। लेकिन यह दूसरी बात है यदि यह बिंदु पर धीमा है तो आपको इसे अपने कार्यक्रम में नहीं करना चाहिए।

मुझे लगता है कि यदि कक्षाओं की वस्तुओं को रखने में कोई बिंदु है जो एक संग्रह में समान अभिभावक नहीं है। हो सकता है कि आप कुछ अमूर्तता पा सकें और फिर फोरैच में सभी ऑब्जेक्ट्स को बेस क्लास में डालें और पॉलिमॉर्फिक कॉल का उपयोग करें।

+0

यह सरणी सूची नमूना मेरा कोड नहीं है। कॉन्वेंट के साथ जेनेरिक बहुत आधुनिक हैं। मैं .NET ढांचे के पुराने स्कूल भागों में "ऑब्जेक्ट कोलेक्शन" का बेहतर संचालन करने में सक्षम हूं। – benwasd

2

संग्रह को दो बार पुनरावृत्त करने से रोकने के लिए और किसी प्रकार का मीठा वाक्यविन्यास रखने के लिए, मैं एक विस्तार विधि के साथ आउंगा जो निर्दिष्ट प्रकारों के लिए चेनिंग फोरैच की अनुमति देता है। मैंने सोचा कि यह अजीब होगा:

static void Main(string[] args) 
    { 
     var ugly = new ArrayList(); 
     ugly.Add("strings are evil"); 
     ugly.Add("yeah"); 
     ugly.Add(1); 
     ugly.Add(3); 
     ugly.Add(1234); 
     ugly.WithType<int>(x => Console.WriteLine("im a lousy int! " + x)) 
      .AndType<string>(x => Console.WriteLine("and im dangerous string: " + x)) 
      .Execute(); 
     Console.ReadKey(); 
    } 

    static TypedCollectionView WithType<T>(this IEnumerable x, Action<T> action) 
    { 
     return new TypedCollectionView(x).AndType(action); 
    } 

    class TypedCollectionView 
    { 
     private readonly IEnumerable collection; 
     private readonly Dictionary<Type, Action<object>> actions = new Dictionary<Type, Action<object>>(); 

     public TypedCollectionView(IEnumerable collection) 
     { 
      this.collection = collection; 
     } 

     public TypedCollectionView AndType<T>(Action<T> action) 
     { 
      actions.Add(typeof(T), o => action((T)o)); 
      return this; 
     } 

     public void Execute() 
     { 
      foreach (var item in collection) 
      { 
       var itemType = item.GetType(); 
       foreach (var action in actions.Where(kv.Key.IsAssignableFrom(itemType)).Select(kv.Value)) 
       { 
        action(item); 
       } 
      } 
     } 
    } 

तो .. अब यह कैसे कम चूसना बनाने के लिए? : डी