मुझे विध्वंसक कब बनाना चाहिए?


185

उदाहरण के लिए:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

मुझे मैन्युअल रूप से विध्वंसक कब बनाना चाहिए? आपको विध्वंसक बनाने की आवश्यकता कब है?


1
C # भाषा इन "डिस्ट्रक्टर्स" को बुलाती है, लेकिन ज्यादातर लोग उन्हें "फाइनल" कहते हैं, क्योंकि यह उनका .NET नाम है और यह C ++ डिस्ट्रक्टर्स (जो काफी अलग हैं) के साथ भ्रम को कम करता है। IDisposable और Finalizers कैसे लागू करें: 3 आसान नियम
स्टीफन क्लीयर

5
जब आप लापरवाह महसूस कर रहे हैं।
कैपड्रैगन

32
मुझे लगता है कि टॉमटॉम का कीबोर्ड खराबी था। कैप लॉक छिटपुट रूप से बंद और चालू था। अजीब।
जेफ लाफे


मैंने ग्रेग बीच के सुझाव के आधार पर डिबगिंग सहायता के रूप में एक विध्वंसक का उपयोग करके समाप्त किया: stackoverflow.com/questions/3832911/…
ब्रायन

जवाबों:


237

UPDATE: यह प्रश्न मेरे ब्लॉग का विषय था 2015 के मई में । महान प्रश्न के लिए धन्यवाद! ब्लॉग को उन झूठों की लंबी सूची के लिए देखें जिन्हें लोग आमतौर पर अंतिम रूप देने के बारे में मानते हैं।

मुझे मैन्युअल रूप से विध्वंसक कब बनाना चाहिए?

लगभग नहीं।

आमतौर पर एक केवल एक विध्वंसक बनाता है जब आपकी कक्षा कुछ महंगे अप्रबंधित संसाधन पर रोक रही होती है जिसे ऑब्जेक्ट के दूर होने पर साफ किया जाना चाहिए। यह सुनिश्चित करने के लिए डिस्पोजेबल पैटर्न का उपयोग करना बेहतर है कि संसाधन को साफ किया जाए। एक विध्वंसक तब अनिवार्य रूप से एक आश्वासन है कि यदि आपकी वस्तु का उपभोक्ता इसे निपटाना भूल जाता है, तो संसाधन अभी भी अंततः साफ हो जाता है। (शायद।)

यदि आप एक विध्वंसक बनाते हैं तो बेहद सावधान रहें और समझें कि कचरा संग्रहकर्ता कैसे काम करता है । विध्वंसक वास्तव में अजीब हैं :

  • वे आपके धागे पर नहीं चलते हैं; वे अपने स्वयं के धागे पर चलते हैं। गतिरोध का कारण मत बनो!
  • एक विध्वंसक से फेंका गया एक अखंड अपवाद बुरी खबर है। यह अपने स्वयं के धागे पर है; इसे पकड़ने वाला कौन है?
  • कंस्ट्रक्टर शुरू होने के बाद एक विध्वंसक को किसी ऑब्जेक्ट पर बुलाया जा सकता है लेकिन कंस्ट्रक्टर के खत्म होने से पहले । ठीक से लिखा गया विध्वंसक, कंस्ट्रक्टर में स्थापित आक्रमणकारियों पर निर्भर नहीं करेगा।
  • एक विध्वंसक वस्तु को फिर से जीवित कर सकता है, मृत वस्तु को फिर से जीवित कर सकता है। यह वास्तव में अजीब है। यह मत करो।
  • एक विध्वंसक कभी नहीं चल सकता है; आप अंतिमकरण के लिए निर्धारित की जा रही वस्तु पर भरोसा नहीं कर सकते। यह शायद होगा, लेकिन यह कोई गारंटी नहीं है।

लगभग कुछ भी नहीं है कि आम तौर पर सच है एक विध्वंसक में सच है। वास्तव में, वास्तव में सावधान रहें। एक सही विध्वंसक लिखना बहुत मुश्किल है।

आपको विध्वंसक बनाने की आवश्यकता कब है?

संकलक के भाग का परीक्षण करते समय जो विनाशकों को संभालता है। मुझे उत्पादन कोड में ऐसा करने की आवश्यकता नहीं है। मैं शायद ही कभी उन वस्तुओं को लिखता हूं जो मानव रहित संसाधनों में हेरफेर करते हैं।


"विध्वंसक निर्माण शुरू होने के बाद एक वस्तु पर बुलाया जा सकता है लेकिन इससे पहले कि निर्माण खत्म हो जाए।" लेकिन मैं फील्ड इनिशियलाइज़र पर भरोसा कर सकता हूँ कि वह सही है?
विन्यासकर्ता

13
@configurator: नहींं। मान लीजिए कि किसी अंतिम वस्तु के साथ किसी वस्तु का तीसरा क्षेत्र आरंभिक कहलाता है जिसे एक स्थिर विधि कहा जाता है जिससे अपवाद को फेंक दिया जाता है। चौथा क्षेत्र इनिशियलर कब चलेगा? कभी नहीँ। लेकिन वस्तु अभी भी आवंटित है और इसे अंतिम रूप दिया जाना चाहिए। हेक, आपके पास यह गारंटी भी नहीं है कि टाइप डबल के क्षेत्र पूरी तरह से आरंभिक थे जब डोर चलता है। डबल लिखने के माध्यम से एक थ्रेड एबॉर्ट हाफ हो सकता था और अब फाइनली को एक आधा-प्रारंभिक आधा-शून्य डबल से निपटना होगा।
एरिक लिपर्ट

1
उत्कृष्ट पोस्ट, लेकिन कहा जाना चाहिए "तब बनाया जाना चाहिए जब आपकी कक्षा किसी महंगी अप्रबंधित वस्तु पर पकड़ बना रही है या बड़ी संख्या में अप्रबंधित वस्तुओं का अस्तित्व है" - एक ठोस उदाहरण के लिए, मेरे पास C # में एक मैट्रिक्स क्लास है जो एक अंतर्निहित देशी + ++ का उपयोग करता है मैट्रिक्स क्लास बहुत भारी उठाने के लिए - मैं बहुत सारे मैट्रिस बनाता हूं - एक "विध्वंसक" इस विशिष्ट मामले में आईडीसिसोपॉलिटरी से कहीं अधिक बेहतर है, क्योंकि यह घर के प्रबंधित और अप्रबंधित पक्षों को बेहतर सिंक में रखता है
मार्क

1
pythonnet जीआईएल को
मानव रहित

3
बहुत बढ़िया लेख एरिक। इसके लिए प्रॉप्स -> "अतिरिक्त बोनस मज़ा: डिबगर में प्रोग्राम को चलाते समय रनटाइम कम आक्रामक कोड जनरेशन और कम आक्रामक कचरा संग्रह का उपयोग करता है, क्योंकि यह एक खराब डीबगिंग का अनुभव है कि जिन वस्तुओं पर आप डिबगिंग कर रहे हैं वे अचानक गायब हो जाते हैं चर का संदर्भ वस्तु के दायरे में है। इसका मतलब है कि अगर आपके पास एक बग है जहां एक वस्तु को बहुत जल्दी अंतिम रूप दिया जा रहा है, तो आप शायद उस बग को डीबगर में पुन: उत्पन्न नहीं कर सकते हैं! "
केन पामर

17

इसे एक "फाइनल" कहा जाता है, और आपको आमतौर पर केवल एक वर्ग के लिए बनाना चाहिए, जिसका राज्य (यानी: फ़ील्ड) में अप्रबंधित संसाधन (यानी: पी / चालान कॉल के माध्यम से पुनर्प्राप्त किए जाने वाले हैंडल को शामिल करना) शामिल हैं। हालाँकि, .NET 2.0 और बाद में, वास्तव में अप्रबंधित संसाधनों की सफाई से निपटने का एक बेहतर तरीका है: SafeHandle । इसे देखते हुए, आपको अंतिम रूप से फिर से लिखने की ज़रूरत नहीं है।


25
@ThomasEding - हाँ यह है । सी # विध्वंसक वाक्यविन्यास का उपयोग करता है, लेकिन यह वास्तव में एक अंतिम रूप दे रहा हैफिर से
JDB को अभी भी

@ जेडडीबी: भाषाई निर्माण को विध्वंसक कहा जाता है। मैं नाम को नापसंद करता हूं, लेकिन इसे कहा जाता है। विध्वंसक घोषित करने के कार्य के कारण संकलक एक अंतिम विधि उत्पन्न करता है जिसमें विध्वंसक के शरीर में जो कुछ भी दिखाई देता है उसके साथ थोड़ा सा आवरण कोड होता है।
सुपरकैट

8

जब तक आपकी कक्षा विंडोज फ़ाइल हैंडल जैसे अप्रबंधित संसाधनों को बनाए रखती है, तब तक आपको इसकी आवश्यकता नहीं है।


5
खैर, वास्तव में, इसे एक विध्वंसक कहा जाता है
डेविड हेफर्नन

2
अब मैं उलझन में हूँ। क्या यह अंतिम रूप देने वाला या विनाशकारी है?

4
सी # कल्पना वास्तव में इसे विनाशकारी कहती है। कुछ इसे गलती के रूप में देखते हैं। stackoverflow.com/questions/1872700/…
Ani

2
@ThomasEding - हाँ यह है । सी # विध्वंसक वाक्यविन्यास का उपयोग करता है, लेकिन यह वास्तव में एक अंतिम रूप दे रहा है
JDB अभी भी मोनिका

2
मुझे यहाँ टिप्पणियों से प्यार है, असली पंटो :)
बेंजोल

4

इसे डिस्ट्रक्टर / फ़ाइनलीज़र कहा जाता है, और आमतौर पर डिस्पोज़्ड पैटर्न को लागू करते समय बनाया जाता है।

यह एक गिरावट का समाधान है जब आपकी कक्षा का उपयोगकर्ता निपटान को कॉल करना भूल जाता है, यह सुनिश्चित करने के लिए कि (अंततः) आपके संसाधन जारी हो जाते हैं, लेकिन आपके पास कोई गारंटी नहीं है कि जब विध्वंसक को बुलाया जाता है।

इस स्टैक ओवरफ्लो प्रश्न में , स्वीकृत उत्तर सही ढंग से दिखाता है कि डिस्पोज़ पैटर्न को कैसे लागू किया जाए। यह केवल तभी आवश्यक है जब आपके वर्ग में कोई ऐसा अनचाहा संसाधन हो जिसे कचरा उठाने वाला स्वयं साफ करने का प्रबंध नहीं करता है।

एक अच्छा अभ्यास वर्ग के उपयोगकर्ता को मैन्युअल रूप से संसाधनों को मुक्त करने के लिए वस्तु का निपटान करने की संभावना के बिना एक अंतिम रूप से लागू नहीं करना है।


वास्तव में यह अच्छा कारण के साथ C # में एक विध्वंसक नहीं कहा जाता है।
टॉमटॉम

14
वास्तव में यह है । मुझे नीचा दिखाने के लिए धन्यवाद क्योंकि आप गलत हैं। इस विशिष्ट मुद्दे के बारे में MSDN लाइब्रेरी देखें: msdn.microsoft.com/en-us/library/66x5fx1b.aspx
indyvind Bråthen

1
@TomTom यह आधिकारिक नाम विध्वंसक है
डेविड

यह वास्तव में एक फॉलबैक विधि नहीं है, यह बस जीसी को प्रबंधित करने की अनुमति देता है जब आपकी वस्तुओं को अप्रबंधित संसाधनों से मुक्त किया जाता है, तो आईडीसोपायरी को लागू करने से आप खुद को प्रबंधित कर सकते हैं।
हसनी

3

जब आपके पास अप्रबंधित संसाधन हैं और आपको यह सुनिश्चित करने की आवश्यकता है कि आपकी वस्तु के चले जाने पर उन्हें साफ किया जाएगा। अच्छा उदाहरण COM ऑब्जेक्ट या फ़ाइल हैंडलर होगा।


2

मैंने एक विध्वंसक (केवल डिबग उद्देश्यों के लिए) यह देखने के लिए उपयोग किया है कि क्या किसी ऑब्जेक्ट को WPF एप्लिकेशन के दायरे में मेमोरी से शुद्ध किया जा रहा है। अगर कचरा संग्रह सही मायने में स्मृति से वस्तु को शुद्ध कर रहा था, तो मैं अनिश्चित था, और यह सत्यापित करने का एक अच्छा तरीका था।


1

विध्वंसक आपकी कक्षा में कूटबद्ध किए गए अप्रबंधित संसाधनों को मुक्त करने का एक निहित तरीका प्रदान करते हैं, वे कहते हैं कि जब जीसी इसके चारों ओर हो जाता है और वे बेस क्लास के अंतिम विधि को निहित करते हैं। यदि आप बहुत से अप्रबंधित संसाधनों का उपयोग कर रहे हैं, तो उन संसाधनों को आईडीआईसोफ़ायर इंटरफ़ेस के माध्यम से मुक्त करने का एक स्पष्ट तरीका प्रदान करना बेहतर है। C # प्रोग्रामिंग गाइड देखें: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.