2010-01-15 19 views
5

प्रत्येक आइटम में एक इंटरफ़ेस है, IItem। साथ ही, एक इंटरफेस IDrawableItem के रूप में जाना जाता है जो आइटम से प्राप्त होता है।कास्टिंग और इंटरफ़ेस विरासत

नीचे दिया गया कोड, एक ड्रॉइंग आइटम खींचने की कोशिश कर रहा है, लेकिन संग्रह के रूप में इस श्रेणी के स्टोर केवल IItem स्वीकार नहीं कर सकते हैं। आप इस वर्ग में IItem से प्राप्त कुछ भी जोड़ सकते हैं, लेकिन अन्य विधियों का उपयोग करके केवल कास्टिंग करके हासिल किया जा सकता है।

foreach (var item in Items) { 
    item.Draw();    // The casting would go here. 
} 

मैं कैसे कास्ट करने के लिए, as आदि ... लेकिन यह स्वीकार्य है पता है? क्या यह सबसे अच्छा अभ्यास है?

बस सोच रहा है कि ऐसे परिदृश्यों को संभालने के अन्य तरीके हैं या नहीं।

+0

नीचे दिया गया कोड, एक ड्रॉइंग आइटम खींचने की कोशिश कर रहा है, लेकिन संग्रह के रूप में इस श्रेणी के स्टोर केवल IItem स्वीकार नहीं कर सकते हैं। - क्यूं कर? डिजाइन के बारे में हमें थोड़ा बताओ। क्या आप इसे बदल सकते हैं? –

+0

जेसन का कोड आपको आपकी दुविधा से बाहर कर देगा। मुद्दा यह है कि क्या यह आपकी वस्तुओं के लिए सही डिजाइन है, और विवरण की 2 पंक्तियों से कहना मुश्किल है। – hackerhasid

+0

शायद ऐसे संग्रह का उपयोग करें जो इसके बजाय IDrawbleItem को संग्रहीत करता है? –

उत्तर

11

उपयोग Enumerable.OfType केवल Items के उन तत्वों को लागू करने को निकालने के लिए IDrawableItem:

:

foreach(var item in Items.OfType<IDrawableItem>()) { 
    item.Draw(); 
} 

सवाल है कि नानुक टिप्पणी में पूछा उपरोक्त कोड शायद निम्न के कोड बराबर में अनुवाद किया जाएगा पता करने के लिए

:
foreach(var item in Items) { 
    if(item is IDrawableItem) { 
     ((IDrawable)item).Draw(); 
    } 
} 
बेशक

, वास्तव में वहाँ पर्दे के पीछे एक इटरेटर कि कुछ इस तरह दिखता है

public static IEnumerable<T> OfType<T>(this IEnumerable<TSource> source) { 
    if(source == null) { 
     throw new ArgumentNullException("source"); 
    } 
    foreach(TSource item in source) { 
     if(item is T) { 
      yield return (T)item; 
     } 
    } 
} 

तो, यह दिखाता है कि हम शायद Items के माध्यम से केवल एक बार फिर से सक्रिय हो जाते हैं। बेशक, कोई आवश्यकता नहीं है कि OfType उपरोक्त की तरह कार्यान्वित किया गया है लेकिन यह समझदारी की बात है।

+0

क्या यह उदाहरण वास्तव में 2 लूप करता है? 1 IDrawableItems प्राप्त करने के लिए और दूसरे के माध्यम से लूप करने के लिए और ड्रा ड्रा। यदि ऐसा है, तो यह बहुत ही सक्षम नहीं है। – Nanook

+2

नहीं, यह परिणाम स्ट्रीम करता है। –

+0

नहीं, यह नहीं है। सभी Linq.Numerable विधियों को एक कस्टम एन्यूमेरेटर का उपयोग करके लागू किया जाता है। ऊपर दिया गया कोड फ़ोरैच (वस्तुओं में var आइटम) जैसे कुछ में अनुवाद करेगा {यदि आइटम IDrawableItem के रूप में IDTableItem उपज वापसी आइटम है; } – herzmeister

1

दो वैकल्पिक समाधान:

  • एक अलग संग्रह में ड्रॉएबल रखें।
  • DrawIfPossible()IItem पर विधि जोड़ें। IDrawableItem को इसे Draw() पर कॉल करने के लिए ओवरराइड करना चाहिए, अन्य IItem() कार्यान्वयनकर्ताओं के पास खाली कार्यान्वयन होना चाहिए।

स्पष्ट प्रकार पूछताछ को एक संकेत माना जाता है कि डिजाइन में कुछ गड़बड़ हो सकती है।

+0

जैसा कि मैंने कहा है, यह एक त्वरित प्रोटोटाइप है जो बदलने की संभावना है। हालांकि मैं डिजाइन के बारे में आपके आखिरी बिंदु के बारे में सहमत हूं। – Finglas

+0

आलोचना के रूप में नहीं था। ऐसे मामले हैं जब टाइपिंग क्वेरी आवश्यक है। क्विक हैक, ऑब्जेक्ट्स को पास करने वाले ढांचे 'आईसीएस्टआईटीडाउनएस्ड्यूड' आदि के रूप में। –

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