2009-12-31 28 views
24

मैं सी # सीखने के लिए काफी नया हूं (जावा & सी ++ पृष्ठभूमि से) और मेरे पास मैन्युअल कचरा निपटान के बारे में कोई सवाल है: क्या सी # में किसी ऑब्जेक्ट को मैन्युअल रूप से नष्ट करना भी संभव है? मुझे IDisposable इंटरफ़ेस के बारे में पता है, लेकिन मान लीजिए कि मैं उस वर्ग से निपट रहा हूं जिसे मैंने नहीं लिखा था और यह इसे लागू नहीं करता है? इसमें .Dispose() विधि नहीं होगी, इसलिए using { } बाहर है, और .Finalize हमेशा protected या private है, इसलिए यह कोई विकल्प नहीं है।मैन्युअल रूप से सी # ऑब्जेक्ट्स

(मैं सिर्फ जानने के लिए सी इस मामले में # में संभव है क्या कोशिश कर रहा हूँ। मैं अगर बाकी सब विफल रहता है मैं वारिस सकता काल्पनिक ImNotDisposable वर्ग इतना है कि यह IDisposable को लागू करता है लगता है।)

+3

शायद आपको इस प्रश्न को स्पष्ट करना चाहिए: क्या आप किसी ऑब्जेक्ट को पूरी तरह से डिलीकेट करना चाहते हैं, या बस इसके विनाशक विधि को निष्पादित करें और ऑब्जेक्ट के संसाधनों को केवल साफ़ करें (केवल)? –

+0

मैंने अनुमान लगाया कि एक दूसरे ने निहित किया है, लेकिन जो कुछ भी मेरे मन में था, वह किसी ऑब्जेक्ट की क्लासनाम() विधि को 'ट्रिगर' करने का कोई तरीका था। –

+0

तो संक्षेप में, जीसी में कलेक्ट() विधि है जो बहुत अधिक या कुछ भी नहीं है, और एक विशिष्ट वस्तु को लक्षित करने का कोई तरीका नहीं है। पकड़ लिया। :) –

उत्तर

24

आप मैन्युअल रूप से .NET ऑब्जेक्ट्स को नष्ट नहीं करते हैं। एक प्रबंधित वातावरण होने के बारे में यह सब कुछ है।

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

इसके बजाय, यह संभवतः का दावा करना बेहतर है कि कोई भी वस्तु जो अप्रबंधित संसाधनों का उपयोग नहीं करती है और आपके प्रोग्राम में किसी भी अन्य वस्तु द्वारा पहुंच योग्य नहीं है, तुरंत नष्ट हो जाती है। मुझे पता है कि ऐसा नहीं होता है, लेकिन इस बिंदु पर वस्तु किसी अन्य की तरह स्मृति की एक ब्लॉक है। आप इसे पुनः प्राप्त नहीं कर सकते हैं और अंततः इसे एकत्रित किया जाएगा, इसलिए यह आपके लिए भी मर सकता है।

IDISposable के बारे में एक अंतिम नोट। आप केवल प्रकार है कि अप्रबंधित संसाधनों लपेट के लिए उपयोग करना चाहिए: सॉकेट, डेटाबेस कनेक्शन, GDI वस्तुओं की तरह बातें, आदि

+4

मैं बाहरी ऑब्जेक्ट्स पर लगाए गए किसी भी ईवेंट को अनलिंक करने का निपटान भी करता हूं। यदि आप ऐसा नहीं करते हैं तो ऑब्जेक्ट को स्मृति से हटाया नहीं जाएगा जब तक कि बाहरी ऑब्जेक्ट न हो, जो कि एप्लिकेशन के जीवनकाल के लिए हो सकता है। –

+1

@MongusPong: 'निपटान' बहुत महत्वपूर्ण है, लेकिन यह वस्तुओं को "नष्ट" नहीं करता है - इसके बजाय यह उन्हें सूचित करता है कि उनकी सेवाओं की अब आवश्यकता नहीं है, ताकि अन्य संस्थाएं (उनकी ओर से कार्य कर रहे हों (यदि कोई अस्तित्व में है) हो सकता है बदले में अधिसूचित किया गया है कि * उनकी * सेवाओं की आवश्यकता नहीं है। – supercat

+0

मैं सामान्य कथन से पूरी तरह से असहमत हूं "आपको केवल उन्हीं प्रकारों के लिए इसका उपयोग करना चाहिए जो अप्रबंधित संसाधनों को लपेटते हैं।" मुझे पता है कि यह पारंपरिक ज्ञान है, लेकिन यदि आप स्मृति रिसाव के मुद्दों में भाग लेते हैं , वस्तुओं को डिस्पोजेबल बनाने के लिए बहुत अच्छा है। कारण यह है कि अच्छी मेमोरी ट्रेसिंग ऐप्स आपको उन वस्तुओं को दिखाने में सक्षम होंगे जिन्हें निपटान किया गया है, लेकिन अभी तक नष्ट नहीं हुआ है। यह आपको स्पष्ट रूप से दिखाता है कि आपने विनाश के लिए क्या चिह्नित किया है, लेकिन नहीं इसके अलावा, यह आपको एक अच्छा मौका देता है, और इवेंट हैंडलर को अनदेखा करने के लिए मानक स्थान देता है और इसलिए जाल ठीक से टूटा हुआ है। –

6

यदि ऑब्जेक्ट पहुंच योग्य नहीं है तो आप GC.Collect() पर कॉल कर सकते हैं और ऑब्जेक्ट नष्ट हो जाएगा। IDisposable की अवधारणा सीएलआर के साथ कुछ लेना देना नहीं है और अधिकतर अतिरिक्त निपटान तर्क करने के लिए लागू करने के लिए उपयोगकर्ता कोड के लिए है। किसी ऑब्जेक्ट पर कॉलिंग डिसपोज़() ऑब्जेक्ट को स्मृति से मुक्त नहीं करेगा, हालांकि यह ऑब्जेक्ट संदर्भों के किसी संसाधन को बहुत अच्छी तरह से निपट सकता है।

मैं जोड़ने चाहिए कि जब तक मैं क्या कहा एक तरह से आवेदनों की 99.9999% में इस लक्ष्य को हासिल करने के लिए, तो आप GC.Collect() फोन कभी नहीं करना चाहिए, क्योंकि यह अक्सर नीचा जाएगा कि यह सुधार लाने के अपने आवेदन के प्रदर्शन के बजाय।

+3

कॉलिंग 'जीसी। कोलेक्ट()' कुछ ऐसा नहीं है जो आपको करना चाहिए, जब तक कि यह * बहुत * अच्छे कारण के लिए न हो। –

+0

इसमें जोड़ने के लिए, यदि ऑब्जेक्ट के कोई और संदर्भ नहीं हैं तो यह केवल ऑब्जेक्ट एकत्र करेगा। – McAden

+1

यह ऑब्जेक्ट के संदर्भों के बारे में नहीं है - यह पहुंच के बारे में है (जो मैं उल्लेख करता हूं)। – Eilon

5

नहीं, आप किसी विशिष्ट वस्तु को नष्ट नहीं कर सकते हैं।

कचरा कलेक्टर का आह्वान करना संभव है, जो वस्तुओं को नष्ट करने के लिए देखेगा, लेकिन यह लगभग कभी भी अच्छा विचार नहीं है।

3

आप चर आप को नष्ट करना चाहते के बाद से बाहर चला जाता है चलाने के लिए कचरा कलेक्टर मजबूर कर सकते हैं दायरा, लेकिन आप आमतौर पर ऐसा नहीं करना चाहते हैं, क्योंकि कचरा कलेक्टर अपने काम करने के लिए छोड़कर अधिक कुशल है।

कचरा संग्रहण को मजबूर करना GC.Collect के साथ किया जा सकता है, लेकिन ऐसा नहीं करें। मेरे 10 वर्षों में .NET डेवलपर के रूप में, मुझे इसकी आवश्यकता नहीं है।

1

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

मुबारक कोडिंग,

स्कॉट

+1

कॉलिंग निपटान ऑब्जेक्ट को फिर से फ़्लैग नहीं करता है दावा करने योग्य, यह आपको कचरा कलेक्टर के आने के इंतजार के बजाय जैसे ही आप उनके साथ किया जाता है, डेटाबेस डेटाबेस जैसे सीमित संसाधनों को रिलीज़ करने की अनुमति देता है और ऑब्जेक्ट को अंतिम रूप देने का समय तय करता है। – Paolo

1

आप नहीं मैन्युअल एक वस्तु को नष्ट कर सकते "सी ++ हटाना की तरह", तुम सब क्या कर सकते हैं बस किसी भी अनन्य संसाधनों वस्तु हासिल कर ली है को बंद करने और अशक्त सब है इस ऑब्जेक्ट के संदर्भ, इसलिए जीसी इसे इकट्ठा कर सकता है, जीसी.कोलेक्ट() को स्वयं भी कॉल नहीं करता है, जीसी प्रक्रिया महंगी है, क्योंकि इसे अन्य सभी धागे को सुरक्षित रूप से स्मृति से वस्तुओं को एकत्रित करने के लिए निलंबित करना है, इसलिए बस भरोसा करें जीसी, और जब आवश्यक हो तो यह बंद हो जाएगा।

+3

वैसे मैं वास्तव में किसी भी संदर्भ चर को myullb = null जैसे शून्य मान पर असाइन नहीं करता; मैं उन्हें सिर्फ दायरे से बाहर जाने की अनुमति दूंगा। –

+1

मैं सहमत हूं, यदि संभव हो तो मैं ऐसा करने की कोशिश करता हूं – bashmohandes

6

हालांकि आप कचरा संग्रहण ट्रिगर कर सकते हैं (आपको सभी पीढ़ियों के लिए जीसी ट्रिगर करने की आवश्यकता है क्योंकि आप यह सुनिश्चित नहीं कर सकते कि अंतिम पीढ़ी किस पीढ़ी में है) आप जरूरी नहीं कि किसी विशेष वस्तु को अंतिम रूप देने के लिए मजबूर हो। आप केवल कचरा कलेक्टर कैसे काम करता है इस बारे में धारणाओं पर निर्भर कर सकते हैं।

फर्टनर्मोर, चूंकि अंतिमकरण अपने धागे पर होता है, तो आपको कचरा संग्रहण ट्रिगर करने के बाद WaitForPendingFinalizers पर कॉल करना चाहिए।

GC.Collect(GC.MaxGeneration); 
GC.WaitForPendingFinalizers(); 

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

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

जेफ रिक्टर ने हाल ही में receiving a notification when garbage collection occurs के लिए एक अच्छी छोटी सी चाल पोस्ट की।

रीको मरिअनी (MSFT) द्वारा Garbage Collector Basics and Performance Hints पर एक और महान लेख

0

कहो तुम एक वर्ग मैट्रिक्स है और आप दो मैट्रिक्स वस्तुओं aMatrix और bMatrix बनाया। सी # में आप किसी ऑब्जेक्ट को मैन्युअल रूप से नष्ट कर सकते हैं (अंतिम रूप दें):

aMatrix = NULL;

जीसी.कोलेक्ट();

कचरा कलेक्टर नोटिस करेगा कि आपका एमैट्रिक्स न्यूल है और इसे नष्ट कर देगा (इसे अंतिम रूप देगा)। चाहे यह एक अच्छा विचार है, एक अलग कहानी है या नहीं।

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