2016-03-12 16 views
7

यदि मैं एक सामान्य प्रकार को लागू करता हूं जो बहुत से प्रकार के पैराम के साथ तत्काल होने का जोखिम उठाता है, तो क्या मुझे कई घोंसले वाले गैर-जेनेरिक प्रकारों से बचने के लिए (जेआईटी प्रदर्शन/कोड आकार इत्यादि के कारण) से बचना चाहिए?क्या मुझे जेनेरिक प्रकारों में नेस्टेड प्रकारों से बचना चाहिए?

उदाहरण:

public class MyGenericType<TKey, TValue> 
{ 
    private struct IndexThing 
    { 
     int row; int col; 
    } 

    private struct SomeOtherHelper 
    { 
     .. 
    } 

    private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { } 

} 

विकल्प है जो समान रूप से अच्छी तरह से काम करता है बाहर गैर-सामान्य प्रकार है, लेकिन फिर वे नामस्थान को दूषित। क्या कोई सर्वोत्तम अभ्यास है?

public class MyGenericType<TKey, TValue> 
{ 
    private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { } 
} 

internal struct IndexThingForMyGenericType 
{ 
    int row; int col; 
} 

internal struct SomeOtherHelper 
{ 
    ... 
} 
+0

हमेशा बाधाओं को मारने के बिना हमेशा अनुकूलित नहीं होता है। बस एक तरह से कोड जो सबसे अधिक समझ में आता है, ज्यादातर यह एक समस्या नहीं होगी।सवाल के बारे में, मुझे नहीं पता लेकिन आप बीसीएल में बहुत से घोंसले वाले निजी वर्ग देख सकते हैं, इसलिए मुझे उस मार्ग पर जाने के लिए एक डिजाइन बिंदु से दिमाग नहीं होगा। जैसा कि आप कहते हैं दूसरा दूसरा भ्रमित हो सकता है – nawfal

+0

यह कोड अर्थात् समान नहीं है। आपके पहले उदाहरण में 'SomeOtherHelper' एक प्रकार का नहीं है क्योंकि यह सामान्य पैरामीटर पर निर्भर करता है। उदाहरण के लिए, 'टाइपऑफ (MyGenericType .SomeOtherHelper) 'टाइपफ़ोफ़ (MyGenericType .SomeOtherHelper) जैसा नहीं है। – Enigmativity

+0

यदि आपकी समस्या नामस्थान में कक्षाएं हैं क्योंकि आप इसे क्लीनर चाहते हैं, तो इसे उप-नेमस्पेस में जोड़ें, उदाहरण के लिए यदि आपका नामस्थान MyNamespace है तो फिर MyNamespace.AccesoryNamespace में जोड़ें। – Gusman

उत्तर

6

सी # प्रत्येक जेनेरिक प्रकार के प्रत्येक नेस्टेड प्रकार स्वाभाविक रूप से सामान्य है। कंपाइलर नेस्टेड प्रकार को सामान्य के रूप में भी (हमारे ज्ञान के बिना) बना देगा। अधिक जानकारी के लिए this article देखें।

यद्यपि जेनेरिक संदर्भ प्रकारों के लिए जेआईटी कोड साझा करते हैं जैसा कि this interview में बताया गया है, इसमें गैर सामान्य वर्गों की तुलना में कुछ ओवरहेड है। प्रत्येक मूल्य प्रकार का अपना जेआईटी कोड मिलता है।

  • यदि प्रकार केवल सामान्य वर्ग में उपयोग किया जाता है - यह एक निजी नेस्टेड प्रकार होने के लिए अधिक समझ में आता है।

  • यदि प्रकार कहीं और उपयोग किया जाता है, तो यह आदर्श रूप से एक गैर नेस्टेड प्रकार (आंतरिक के रूप में) होना चाहिए।

जिसके अनुसार, अपने नेस्टेड प्रकार इस मामले में प्रकार पैरामीटर T का उपयोग नहीं कर रहा है, यह सामान्य प्रकार का एक नेस्टेड प्रकार होना और इस तरह यह रूप में अच्छी तरह एक सामान्य प्रकार बनने की जरूरत नहीं है।

अधिकांश समय इससे कोई फर्क नहीं पड़ता है, लेकिन यदि आप रनटाइम पर बनाए गए कई प्रकार से चिंतित हैं, तो आप अपने जेनेरिक प्रकार को गैर सामान्य आधार वर्ग के लिए दोबारा कर सकते हैं जो आपके नेस्टेड प्रकारों के लिए एक कंटेनर प्रकार के रूप में कार्य करता है और नेस्टेड प्रकारों को संरक्षित के रूप में बेनकाब करें।

public class NonGenericBase 
{ 
    protected struct IndexThing 
    { 
     int row; int col; 
    } 

    protected struct SomeOtherHelper 
    { 
     .. 
    } 
} 

public class MyGenericType<TKey, TValue> : NonGenericBase 
{ 
    private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { } 

} 

इस तरह आप एक ही नेस्टेड प्रकार साझा कर रहे हैं। कोई रनटाइम ओवरहेड नहीं। प्रत्येक प्रकार पैरामीटर के लिए कोई अलग प्रकार नहीं। अब typeof(MyGenericType<int, string>.SomeOtherHelper)typeof(MyGenericType<long, bool>.SomeOtherHelper) के बराबर होगा।

+0

मुझे लगता है कि गैर-जेनेरिक बेस क्लास जाने का रास्ता हो सकता है। केवल बुरी चीज यह है कि यह वास्तव में उपयोगी नहीं है, फिर भी यह मेरे सामान्य प्रकार के रूप में सार्वजनिक रूप से (कम से कम) होना चाहिए, इसलिए अब मैंने सार्वजनिक एपीआई को प्रदूषित किया है न केवल आंतरिक :( मुझे अभी भी लगता है कि यह है हालांकि कम से कम खराब समाधान। धन्यवाद –

1

हालांकि यह सवाल पूरी तरह से जवाब नहीं देता है, ध्यान दें कि संदर्भ प्रकारों के लिए कोड साझा किया जाता है, क्योंकि आंतरिक रूप से यह पॉइंटर्स के बारे में है। तो आपको कोड बेस को फिसलने के बारे में चिंता करने की ज़रूरत नहीं है। this उत्तर से उद्धरण (एंडर्स हेजल्सबर्ग उद्धरण है)। हम निष्पादन मूल कोड का एक अनूठा प्रतिलिपि बना सकते हैं -

अब, क्या हम तो सभी प्रकार instantiations कि मूल्य प्रकार-तरह के List<int>, List<long>, List<double>, List<float> के रूप में कर रहे हैं के लिए है। तो List<int> अपने स्वयं के कोड प्राप्त करता है। List<long> अपना खुद का कोड प्राप्त करता है। List<float> अपने खुद के कोड प्राप्त करता है। सभी संदर्भ प्रकारों के लिए हम कोड साझा करते हैं, क्योंकि वे प्रतिनिधित्वत्मक रूप से समान हैं। यह सिर्फ पॉइंटर्स है।

+0

हां, लेकिन यह एक ही आकार के मूल्य प्रकारों के लिए भी साझा नहीं किया गया है, इसलिए 'MyGenericType IndexThing' afaik। 'MyGenericType IndexThing' आदि का पुन: उपयोग नहीं करेगा। 2+ प्रकार पैरामीटर के साथ मुझे एक संयोजन विस्फोट का डर है, भले ही सभी संदर्भ उदाहरण कोड साझा करें! –

+0

@AndersForsgren हाँ, मुझे पता है। यही कारण है कि मैंने कहा कि यह * संदर्भ * प्रकारों के लिए साझा किया गया है। – Kapol

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