C # में एक विध्वंसक और एक वर्ग में एक अंतिम विधि के बीच क्या अंतर है?


97

एक वर्ग में एक विध्वंसक और एक अंतिम विधि के बीच एक होने पर क्या अंतर है?

मुझे हाल ही में पता चला है कि विज़ुअल स्टूडियो 2008 एक विध्वंसक को अंतिम विधि का पर्याय मानता है, जिसका अर्थ है कि विज़ुअल स्टूडियो आपको एक साथ एक कक्षा में दोनों विधियों को परिभाषित नहीं करने देगा।

उदाहरण के लिए, निम्नलिखित कोड टुकड़ा:

class TestFinalize
{
    ~TestFinalize()
    {
        Finalize();
    }

    public bool Finalize()
    {
        return true;
    }
}

विध्वंसक में अंतिम रूप देने के लिए कॉल पर निम्नलिखित त्रुटि देता है:

कॉल निम्न विधियों या गुणों के बीच अस्पष्ट है: 'TestFinalize। ~ TestFinalize ()' और 'TestFinalize.Finalize ()'

और यदि कॉल को अंतिम रूप दिया जाता है, तो यह निम्नलिखित त्रुटि देता है:

टाइप 'ManagementConcepts.Service.TestFinalize' पहले से ही एक पैरामीटर पैरामीटर के साथ 'फाइनल' नामक एक सदस्य को परिभाषित करता है

जवाबों:


68

सी # में एक विध्वंसक System.Object.Finalizeविधि को ओवरराइड करता है। आपको ऐसा करने के लिए डिस्ट्रक्टर सिंटैक्स का उपयोग करना होगा। मैन्युअल रूप से ओवरराइड करने Finalizeसे आपको एक त्रुटि संदेश मिलेगा।

मूल रूप से आप अपने Finalizeविधि घोषणा के साथ जो करने की कोशिश कर रहे हैं वह आधार वर्ग की विधि को छिपा रहा है। यह संकलक को चेतावनी जारी करने का कारण बनेगा जिसे newसंशोधक का उपयोग करके चुप कराया जा सकता है (यदि यह काम करने जा रहा था)। यहां ध्यान देने वाली महत्वपूर्ण बात यह है कि आप दोनों एक ही समय में समान नाम के साथ एक सदस्य की घोषणा नहीं कर सकते हैं, इसलिए विध्वंसक और विधि दोनों में त्रुटि होगी (लेकिन आप कर सकते हैं , हालांकि अनुशंसित नहीं है, एक विधि घोषित करें यदि आप एक विध्वंसक घोषित नहीं कर रहे हैं)।overridenewFinalizepublic new void Finalize()


71

विकिपीडिया में एक फ़ाइनलाइज़र और फ़ाइलेज़र लेख में एक विध्वंसक के बीच अंतर पर कुछ अच्छी चर्चा है ।

सी # वास्तव में एक "सच" विध्वंसक नहीं है। वाक्य-विन्यास एक C ++ विध्वंसक जैसा दिखता है, लेकिन यह वास्तव में एक अंतिम रूप है। आपने इसे अपने उदाहरण के पहले भाग में सही लिखा है:

~ClassName() { }

ऊपर एक Finalizeफ़ंक्शन के लिए सिंटैक्टिक चीनी है । यह सुनिश्चित करता है कि आधार में फाइनल को चलाने की गारंटी है, लेकिन Finalizeफ़ंक्शन को ओवरराइड करने के लिए अन्यथा समान है । इसका मतलब है कि जब आप डिस्ट्रक्टर सिंटेक्स लिखते हैं, तो आप वास्तव में फाइनल लिखते हैं।

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

C ++ के "विध्वंसक" शब्द का Microsoft का उपयोग भ्रामक है, क्योंकि C ++ में इसे ऑब्जेक्ट के नष्ट होते ही उसी थ्रेड पर निष्पादित किया जाता है या स्टैक से पॉपअप किया जाता है, जबकि C # में इसे किसी अन्य समय पर एक अलग थ्रेड पर निष्पादित किया जाता है।


मैं तर्क दूंगा कि विध्वंसक और अंतिम रूप देने वाले के बीच ऐसा अंतर एक महत्वपूर्ण है। हालांकि, केवल वे जो इस बात की परवाह करते हैं कि हुड के नीचे क्या चल रहा है, वे भेद के बारे में परवाह करेंगे।
काइल बरन

1
यह भी ध्यान दें कि ECMA-334 ने बहुत पहले ही औपचारिक रूप से "विध्वंसक" और "फाइनल" को तोड़ दिया था। मुझे नहीं पता कि एमएस अभी भी अपने विनिर्देशों में भ्रामक शब्द पर जोर क्यों दे रहा है।
फ्रैंकहब

कम से कम मोनो के साथ काम करने से, C # वास्तव में C ++ के बाद मॉडलिंग की जाती है, और अधिकांश देशी C # ऑब्जेक्ट C ++ ऑब्जेक्ट हैं। जिस तरह से कम्पाइलर ने मोनो को संकलित किया है वह बताता है कि उन C ++ ऑब्जेक्ट्स को कैसे नष्ट किया जाता है, और इसी तरह, C # ऑब्जेक्ट को अंतिम रूप देने के लिए C ++ तक प्रचार करता है और उन डिस्ट्रक्टर्स को कॉल करता है। अंतर हुड के तहत समझ में आता है, लेकिन यह अभी भी वास्तव में सी # पर लागू नहीं होता है।
केनजी

20

यहाँ पाया गया: http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. नाशक

    वे विशेष विधियाँ हैं जिनमें ऑब्जेक्ट के लिए क्लीन अप कोड होता है। आप उन्हें स्पष्ट रूप से अपने कोड में नहीं बुला सकते हैं क्योंकि उन्हें जीसी द्वारा अंतर्निहित कहा जाता है। C # में उनका वही नाम है जो ~चिन्ह से पहले वर्ग का नाम था । पसंद-

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }

    VB.NET में, System.Object वर्ग की अंतिम विधि को ओवरराइड करके विनाशकों को लागू किया जाता है।

  2. निपटान

    ये कक्षा में किसी भी अन्य तरीके की तरह हैं और स्पष्ट रूप से कहे जा सकते हैं, लेकिन उनके पास वस्तु को साफ करने का एक विशेष उद्देश्य है। डिस्पोज़ मेथड में हम ऑब्जेक्ट के लिए क्लीन अप कोड लिखते हैं। यह महत्वपूर्ण है कि हमने डिस्पोजल पद्धति में सभी अप्रबंधित स्रोतों जैसे डेटाबेस कनेक्शन, फाइल्स आदि को मुक्त कर दिया है। डिस्पोजल पद्धति को लागू करने वाले वर्ग को आइडीएसोपायरी इंटरफ़ेस को लागू करना चाहिए। डिस्पोज़ विधि को उस वस्तु के लिए GC.SuppressFinalize पद्धति को कॉल करना चाहिए, यदि यह डिस्पोज़ हो रही है तो क्लास में विध्वंसक होता है क्योंकि यह ऑब्जेक्ट को साफ करने के लिए पहले ही काम कर चुका होता है, तब कचरा संग्रहकर्ता के लिए ऑब्जेक्ट की अंतिम विधि को कॉल करना आवश्यक नहीं होता है। संदर्भ: http://msdn2.microsoft.com/en-us/library/aa720161(VS.71).aspx

  3. अंतिम रूप

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

    नोट: C # में, अंतिम विधि को ओवरराइड नहीं किया जा सकता है, इसलिए आपको विध्वंसक का उपयोग करना होगा जिसका आंतरिक कार्यान्वयन MSIL में अंतिम विधि को ओवरराइड कर देगा। लेकिन VB.NET में, अंतिम विधि ओवरराइड हो सकती है क्योंकि यह सहायक अवरोधक विधि का समर्थन करती है।

अपडेट: यहां दिलचस्प अर्ध-संबंधित धागा


1
You should only implement a Finalize method to clean up unmanaged resources: आपने इसे अंतिम रूप दिया। निपटान के साथ भी?
hqt

@hqt: वे मामले जहाँ किसी को Disposeबहुत अधिक लागू करना चाहिए , जहाँ किसी को अंतिम रूप देना चाहिए। कार्यान्वित करें Disposeयदि यह संभावना है कि वर्ग या एक व्युत्पन्न वर्ग का उदाहरण सीधे अप्रबंधित संसाधन के लिए सीधे बात होगी, या सीधे एक अप्रबंधित संसाधन को सीधे रखने के लिए अंतिम चीज होगी, या सीधे सीधे खुद के लिए अंतिम चीज होगी। आदि केवल Finalizeसंसाधन सफाई के लिए लागू करते हैं यदि किसी का वर्ग <i> सीधे </ i> एक अप्रबंधित संसाधन का मालिक है <i> और लगभग कुछ भी नहीं </ i> - बहुत संकीर्ण परिदृश्य।
सुपरकैट

@hqt: यदि एक वर्ग सीधे अप्रबंधित संसाधनों का मालिक होगा और अन्य वस्तुओं के संदर्भ भी रखता है, तो अनवांटेड संसाधनों को आम तौर पर अपने स्वयं के अंतिम वर्ग में विभाजित किया जाना चाहिए (जो आदर्श रूप से किसी और चीज के लिए कोई मजबूत संदर्भ नहीं रखना चाहिए), जिसका अर्थ है कक्षा जो अन्य वस्तुओं का संदर्भ रखता है, वह केवल "स्वयं की अप्रबंधित संसाधनों की चीजें" होगा, जो स्वयं संसाधनों के मालिक होने के बजाय, और इस प्रकार उन्हें अंतिम रूप देने की आवश्यकता नहीं होगी।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.