c# "उपज" के लिए कंपाइलर-जनरेटेड गणनाकर्ता एक संरचना क्यों नहीं है?




struct heap (2)

उस क्लास का उपयोग केवल इंटरफ़ेस के माध्यम से ही किया जाएगा। यदि यह एक संरचना थी, तो यह समय का 100% बॉक्स्ड होगा, जिससे यह कक्षा का उपयोग करने से कम कुशल हो।

आप इसे बॉक्स के रूप में परिभाषित नहीं कर सकते, जैसा कि समय के संकलन पर टाइप करने में असंभव है, क्योंकि जब आप कोड संकलित करना शुरू करते हैं तो यह अस्तित्व में नहीं है

IEnumerator कस्टम कार्यान्वयन को लिखते समय आप कोड संकलित करने से पहले वास्तविक अंतर्निहित प्रकार का पर्दाफाश कर सकते हैं, जिससे बॉक्सिंग किए बिना इसे संभावित रूप से उपयोग किया जा सकता है।

IEnumerator / IEnumerable के yield पद्धतियों और गलतियों के लिए कंपाइलर-जनरेट किए गए कार्यान्वयन एक वर्ग लगता है, और इसलिए ढेर पर आवंटित किया जाता है। हालांकि, अन्य। NET प्रकार जैसे List<T> विशेष रूप से struct एन्युमरेटर्स को बेकार स्मृति आवंटन से बचने के लिए वापस लौटते हैं। ग # पद की गहराई में सी # के त्वरित अवलोकन से, मुझे कोई कारण नहीं पता है कि यह यहां क्यों नहीं हो सकता।

क्या मैं कुछ भूल रहा हूँ?


Servy सही ढंग से आपके प्रश्न का उत्तर दिया - एक सवाल है जो आपने खुद को एक टिप्पणी में उत्तर दिया था:

मुझे एहसास हुआ कि जब से वापसी का प्रकार एक इंटरफ़ेस होता है, तो वैसे भी बॉक्सिंग मिलेगा, है ना?

सही। आपका अनुवर्ती प्रश्न यह है:

एक स्पष्ट रूप से टाइप किए गए गणक (जैसे List<T> करता है) को वापस करने के लिए विधि को परिवर्तित नहीं किया जा सकता है?

तो आपका विचार यहाँ है कि उपयोगकर्ता लिखता है:

IEnumerable<int> Blah() ...

और कंपाइलर वास्तव में एक विधि उत्पन्न करता है जो BlahEnumerable रिटर्न BlahEnumerable जो एक स्ट्रक्चर है जो IEnumerable<int> लागू करता है, लेकिन उपयुक्त GetEnumerator आदि विधियों और गुणों के साथ जो मुक्केबाज़ को खत्म करने के लिए "पैटर्न मेलिंग" सुविधा की अनुमति देता है।

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

  • मान लें कि विधि आभासी है। इसे ओवरराइड कैसे किया जा सकता है? वर्चुअल ओवरराइड विधि का वापसी प्रकार बिल्कुल ओवरराइड विधि से मेल खाना चाहिए। (और इसी प्रकार: विधि एक और विधि को अध्यारोहित करती है, विधि एक इंटरफ़ेस की विधि लागू करती है, और इसी तरह।)

  • मान लीजिए विधि एक प्रतिनिधि Func<IEnumerable<int>>Func<T> में संप्रदाय है, लेकिन संप्रदाय संदर्भ प्रकार के प्रकार तर्क के लिए ही लागू होता है। कोड ऐसा दिखता है जैसे यह एक IEnumerable<T> लेकिन वास्तव में यह एक मूल्य प्रकार देता है जो सह-संगत नहीं है- IEnumerable<T> साथ संगत, केवल असाइनमेंट संगत

  • समझे कि हमारे पास void M<T>(T t) where T : class और हम M(Blah()) । हमें यह पता लगाना है कि T IEnumerable<int> , जो बाधा जांच को पारित करता है, लेकिन संरचना प्रकार बाधा जांच को पारित नहीं करता है

और इसी तरह। आप तेजी से थ्रीज़ कंपनी (लड़के मैं यहाँ अपने आप को डेटिंग कर रहा हूँ) के एक एपिसोड में समाप्त होता है, जहां एक छोटा झूठ एक बड़ी आपदा के साथ मिलकर समाप्त होता है। यह सब संग्रह संग्रह की एक छोटी राशि को बचाने के लिए। इसके लायक नहीं।

मैं हालांकि ध्यान दें कि संकलक द्वारा बनाई गई क्रियान्वयन एक दिलचस्प तरीके से संग्रह दबाव को बचाता है। पहली बार GetEnumerator को लौटे जाने योग्य संख्या पर बुलाया जाता है, एन्युमेरेबल स्वयं एक गणक में बदल जाता है । बेशक दूसरी बार राज्य अलग है इसलिए यह एक नया ऑब्जेक्ट आवंटित करता है। चूंकि 99.99% संभावना यह है कि एक अनुक्रम क्रम में एक बार गणना करता है, इसलिए यह संग्रह दबाव पर बड़ी बचत होती है।





yield