2008-12-21 11 views
10

मैंने देखा कि List<T>struct के रूप में अपने गणक को परिभाषित करता है, जबकि ArrayList अपने गणक को class के रूप में परिभाषित करता है। क्या फर्क पड़ता है? अगर मैं अपनी कक्षा के लिए एक गणक लिखना चाहता हूं, तो कौन सा बेहतर होगा?गणनाकर्ता कार्यान्वयन: संरचना या कक्षा का उपयोग करें?

संपादित करें: मेरी आवश्यकताओं को yield का उपयोग करके पूरा नहीं किया जा सकता है, इसलिए मैं अपने स्वयं के एक गणक को लागू कर रहा हूं। उस ने कहा, मुझे आश्चर्य है कि List<T> की लाइनों का पालन करना बेहतर होगा या इसे एक संरचना के रूप में कार्यान्वित करना बेहतर होगा।

+1

मुझे यह जानने में बेहद दिलचस्पी होगी कि आपको उपज रिटर्न का उपयोग करके समस्या का सामना करना पड़ा। –

+0

1) मुझे "कंपाइलर जादू" से बहुत नफरत है जिसके लिए मुझे यकीन नहीं है कि आउटपुट क्या होगा। (हालांकि मैं इसे सरल परिस्थितियों के लिए उपयोग करूँगा।) –

+0

2) मैं ऐसी सूची का समर्थन करना चाहता हूं जिसे पुनरावृत्ति के दौरान संशोधित किया जा सके। सामान्य इटरेटर अर्थशास्त्र ने इसे मना कर दिया। (और मुझे नहीं पता कि संकलक कैसे जानता होगा कि मेरी सूची संशोधित की गई थी!) –

उत्तर

9

अन्य लोगों की तरह, मैं एक कक्षा का चयन करूंगा। उत्परिवर्तनीय structs बुरा हैं। (और के रूप में जारेड पता चलता है, मैं एक iterator ब्लॉक का उपयोग करेंगे। हाथ-कोडिंग एक प्रगणक सही पाने के लिए बारीकियों है।)

एक परिवर्तनशील struct के कारण समस्याओं की जा रही सूची प्रगणक का एक उदाहरण के लिए this thread देखें ...

+0

ठीक है, यह उदाहरण साबित हुआ कि मुझे इसे एक वर्ग बनाना चाहिए। :) लेकिन इस तरह से सूची क्यों लागू की गई है? इसे सही क्यों नहीं किया गया था? –

+0

अब इसे बदलने के लिए निश्चित रूप से बहुत देर हो चुकी है - लेकिन मुझे नहीं पता कि इसे पहली जगह क्यों बनाया गया था। संभावित रूप से दक्षता के नाम पर - लेकिन एक बुरी कॉल, आईएमओ। –

+1

मुझे लगता है कि यह एक गणक की वर्तमान स्थिति को एक अन्य चर में प्रतिलिपि बनाकर 'सहेजा गया' हो सकता है - मैंने हाल ही में लिंक की सूची स्लाइस करने के लिए इस 'फीचर' का उपयोग किया है (लिंकडलिस्ट के रूप में। एन्यूमेरेटर भी एक है संरचना) – thecoop

5

इसे yield return का उपयोग करके लिखें।

कारण है कि आप अन्यथा, class या struct के बीच चयन कर सकते हैं यदि आप बनाने के लिए के रूप में यह एक struct तो यह जैसे ही यह एक अंतरफलक के रूप दिया जाता है बॉक्सिंग हो जाता है, इसलिए यह एक struct सिर्फ जगह लेने के लिए अतिरिक्त नकल का कारण बनता है बना रही है। उस बिंदु को नहीं देख सकता!

+3

जो प्रश्न पूछता है: सूची संरचना संरचना का उपयोग क्यों करती है? –

+0

जब तक किसी के कारण यह लाभकारी न हो, तब तक हमें यह समझना होगा कि माइक्रोस्कोर्फ जिम्मेदार है क्योंकि इसके लिए अस्थायी रूप से पागल हो गया है। –

4

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

मेरी राय में, structs अपरिवर्तनीय होना चाहिए, इसलिए मैं एक वर्ग का उपयोग करता हूं।

8

सी # में एक गणक लिखने का सबसे आसान तरीका "उपज वापसी" पैटर्न के साथ है। उदाहरण के लिए।

public IEnumerator<int> Example() { 
    yield return 1; 
    yield return 2; 
} 

यह पैटर्न हुड के नीचे सभी गणक कोड उत्पन्न करेगा। यह आपके हाथों से निर्णय लेता है।

1

@Earwicker पर विस्तार करने के लिए: आमतौर पर एक गणक प्रकार लिखने से बेहतर होता है, और इसके बजाय संकलक इसे आपके लिए लिखने के लिए yield return का उपयोग करता है। ऐसा इसलिए है क्योंकि ऐसी कई महत्वपूर्ण सूक्ष्मताएं हैं जिन्हें आप याद कर सकते हैं यदि आप इसे स्वयं करते हैं।

इसका उपयोग कैसे करें इसके बारे में कुछ और विवरणों के लिए "What is the yield keyword used for in C#?" SO प्रश्न देखें। पता चलता है कि आप कैसे yield return बिना ठीक से पुनरावर्तक लागू करने के लिए, जो दिखाता है कि यह सिर्फ कैसे जटिल है, और तुम क्यों:

इसके अलावा Raymond Chen ब्लॉग पोस्ट की एक श्रृंखला (भागों 1, 2, 3, और 4 "The implementation of iterators in C# and its consequences") है केवल yield return का उपयोग करना चाहिए।

1

कुछ blogposts है जो वास्तव में इस समस्या को कवर करता है। असल में, गणनाकर्ता structs वास्तव में वास्तव में एक बुरा विचार है ...

+0

'foreach' द्वारा उपयोग की जाने वाली चीज़ को रखने के लिए कुछ भी नहीं होगा, यदि यह' inumerable .GetEnumerator' द्वारा लौटाया गया एक समान प्रकार नहीं होने का एक साफ तरीका था। दिलचस्प बात यह है कि यह चर-प्रकार के अनुमान के लिए नहीं था, इससे कोई फर्क नहीं पड़ता कि 'GetEnumerator' ने एक संरचना या कक्षा वापस कर दी है, क्योंकि 'IENumerator ' पर वापसी मान निर्दिष्ट करने से प्रभावी रूप से इसे क्लास ऑब्जेक्ट में बदल दिया जाता है (यद्यपि कुछ हद तक -ब्रोकन 'बराबर' विधि)। समस्या 'var myEnumerator = thing.GetEnumerator(); 'के साथ है। – supercat

5

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

इसके अलावा, मुझे नहीं लगता कि उत्परिवर्तनीय structs कुछ पोस्ट किए गए उदाहरणों में समस्याओं का स्रोत हैं, लेकिन प्रोग्रामर जिनके पास मूल्य प्रकार काम करने की अच्छी समझ नहीं है।

+0

मैं नहीं देख सकता कि कैसे 'संरचना' गणनाकर्ता कचरा उत्पादन को रोक देगा। क्या आप एक ही गणक की कई प्रतियों के साथ समाप्त होने की अधिक संभावना नहीं रखते हैं, क्योंकि यह एक 'एन्यूमर' ऑब्जेक्ट ऑब्जेक्ट ऑब्जेक्ट के विपरीत है? या मूल्य प्रकारों को कचरा इकट्ठा करने की आवश्यकता नहीं है? – stakx

+0

मूल्य प्रकार संदर्भ प्रकार के रूप में कचरा-संग्रह नहीं होते हैं। संदर्भ प्रकार ढेर पर रहते हैं, जबकि मूल्य प्रकार ढेर पर रहते हैं। इसलिए जब संदर्भ प्रकार जीसी ढेर को संकुचित करके हटा दिया जाता है (यदि आपके पास बड़ा, जटिल ढेर होता है तो धीमा हो सकता है); स्टैक पॉपिंग (बहुत तेज़) द्वारा मूल्य प्रकारों को हटा दिया जाता है। – zigzag

+0

आमतौर पर आपको कचरा उत्पादन के बारे में चिंता करने की आवश्यकता नहीं है क्योंकि जीसी पर्याप्त तेज़ होगा और यह प्रदर्शन बाधा नहीं होगी। लेकिन उच्च आवृत्ति कोड जैसे विशेष मामलों में, ढेर पर बहुत से आवंटन जीसी को सामान्य से अधिक बार चलाने के कारण प्रदर्शन समस्याओं का कारण बन सकता है। (उदाहरण के लिए खेल में प्रत्येक फ्रेम की कई नई वस्तुओं को आवंटित करना) – zigzag

2

IEnumerable<T> के किसी भी कार्यान्वयन को कक्षा वापस करनी चाहिए। यह GetEnumerator विधि के प्रदर्शन कारणों के लिए उपयोगी हो सकता है जो एक संरचना लौटाता है जो गणना के लिए आवश्यक विधियों को प्रदान करता है लेकिन IEnumerator<T> लागू नहीं करता है; यह विधि IEnumerable<T>.GetEnumerator से अलग होनी चाहिए, जिसे स्पष्ट रूप से कार्यान्वित किया जाना चाहिए।

इस दृष्टिकोण का उपयोग कक्षा में किसी फोरैच या "प्रत्येक के लिए" लूप का उपयोग करके एन # या vb.net या किसी भी संदर्भ में गणना करने के लिए किया गया है, जहां कोड गणना कर रहा है, यह पता चल जाएगा कि गणनाकर्ता एक है संरचना, लेकिन उन नुकसानों से बचें जो अन्यथा तब होती हैं जब गणनाकर्ता बॉक्सिंग हो जाता है और मूल्य से गुजरता है।

+1

यह ध्यान देने योग्य है कि अधिकांश दैनिक अनुप्रयोगों में प्रदर्शन लाभ का यह स्तर शायद ही कभी महत्वपूर्ण है। देवताओं को एक संरचना गणनाकर्ता में गोता लगाने से पहले वास्तविक परेशानी के स्थानों को खोजने के लिए एक प्रोफाइलर का उपयोग करना चाहिए। फिर भी, यह एक वैध तकनीक है, और मैंने इसे दो बार अच्छे प्रभाव के लिए उपयोग किया है। –

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