2009-09-26 21 views
8

क्या मुझे भरोसा है कि एक वस्तु नष्ट हो गई है और सी # में दायरे से बाहर होने पर इसके विनाशक को तत्काल बुलाया जाता है?सी # - क्या दायरे से बाहर निकलने पर वस्तुओं को तुरंत नष्ट कर दिया जाता है?

मुझे लगता है कि यह कई सामान्य कोडिंग प्रथाओं (जैसे लेनदेन ऑब्जेक्ट्स) इस व्यवहार पर भरोसा करते हैं, लेकिन मुझे कचरा संग्रह के साथ काम करने के लिए बहुत उपयोग नहीं किया जाता है और इस तरह की भाषाएं आमतौर पर कैसे व्यवहार करती हैं, इस बारे में बहुत कम जानकारी है।

धन्यवाद।

+0

@RA के साथ है आईआरएल करने के लिए काम करता है :) अब कुछ उदाहरण जोड़ा गया है, उम्मीद है कि यह और भी स्पष्ट करता है। –

उत्तर

24

नहीं, नेट और हेन्स सी # कचरा संग्रह स्मृति प्रबंधन पर निर्भर करता है। तो विनाशकों (जो नेट में फाइनलाइजर्स कहा जाता है) तब तक नहीं कहा जाता है जब तक कि जीसी वस्तुओं को नष्ट करने के लिए उचित न हो।

इसके अतिरिक्त: सी # में अधिकांश "नियमित" वस्तुओं में विनाशक नहीं होते हैं। यदि आपको विनाशक पैटर्न की आवश्यकता है तो आपको को Dispose Pattern के साथ लागू करना चाहिए। डिस्पोजेबल ऑब्जेक्ट्स पर आपको यह भी सुनिश्चित करना चाहिए कि निपटान विधि को using keyword या सीधे विधि को कॉल करने के साथ कहा जाता है।

आगे (उम्मीद है) स्पष्ट करने के लिए: नेटिन में निर्धारिक निपटान उपयोगी है उदा। जब आपको उन संसाधनों को स्पष्ट रूप से मुक्त करने की आवश्यकता होती है जिन्हें .NET रनटाइम द्वारा प्रबंधित नहीं किया जाता है। ऐसे संसाधनों के उदाहरण फ़ाइल हैंडल, डेटाबेस कनेक्शन इत्यादि हैं। आमतौर पर यह महत्वपूर्ण है कि इन संसाधनों को जल्द से जल्द मुक्त कर दिया जाए क्योंकि उन्हें अब आवश्यकता नहीं है। इस प्रकार हम जीसी को मुक्त करने के लिए इंतजार नहीं कर सकते हैं।

नेट जीसी की गैर-निर्धारिती दुनिया में निर्धारिक निपटान (सी ++ के दायरे के व्यवहार के समान) प्राप्त करने के लिए, नेट क्लास IDISposable इंटरफेस पर भरोसा करते हैं। Dispose Pattern से उधार, यहाँ कुछ उदाहरण हैं:

सबसे पहले, एक डिस्पोजेबल संसाधन instantiating और फिर दे वस्तु क्षेत्र से बाहर जाना, यह जीसी करने के लिए वस्तु निपटान के लिए छोड़ देंगे:

1. { 
2.  var dr = new DisposableResource(); 
3. } 

करने के लिए

1. { 
2.  var dr = new DisposableResource(); 
3. 
4.  ... 
5. 
6.  dr.Dispose(); 
7. } 

लेकिन क्या कुछ लाइन 2 और 6 के बीच गलत हो जाता है, तो: समस्याओं का समाधान कर इस हम स्पष्ट रूप से वस्तु निपटान कर सकते हैं? निपटान नहीं किया जाएगा। आगे यह सुनिश्चित करने के निपटान के अंत में किसी भी अपवाद हम निम्न कर सकते हैं की परवाह किए बिना कहा जाएगा:

1. var dr = new DisposableResource(); 
2. try 
3. { 
4.  ... 
5. } 
6. finally 
7. { 
8.  dr.Dispose(); 
9. } 

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

1. using (var dr = new DisposableResource()) 
2. { 
3.  ... 
4. } 
+1

प्रश्न पूछने वाले को सी # विनाशक की सूक्ष्मताएं नहीं पता हैं, इसलिए मुझे नहीं लगता कि आपको केवल एक विनाशक को अंतिम रूप देना चाहिए और इसके साथ किया जाना चाहिए। सी ++ विनाशक और सी # विनाशक * बहुत अलग चीजें हैं। * – Joren

+1

यह भी ध्यान रखें कि .NET कचरा संग्रह "पीढ़ी" आधारित है, इसलिए एक वस्तु संभावित रूप से जनरेशन 0 संग्रह द्वारा एकत्रित कचरा हो सकती है, लेकिन पूरी तरह से नष्ट नहीं हुई है "या स्मृति से" हटा दिया "। वीक संदर्भों जैसी चीजों के बारे में भी सोचें जिससे एक वस्तु कचरा एकत्र की जा सकती है, लेकिन फिर भी आपके आवेदन के कोड द्वारा सुलभ हो सकती है! असल में, एक ऑब्जेक्ट तब तक चलता रहेगा जब तक रनटाइम इसे चाहता है। इस मामले में आपके पास कोई बात नहीं है! ;) (http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/) – CraigTP

+0

@ पीटर: आपकी प्रतिक्रिया के लिए धन्यवाद। क्या आप सुझाव दे रहे हैं कि IDISposable उदाहरण C++ में देखे गए दायरे के व्यवहार को प्राप्त करने का एक तरीका प्रदान करता है? क्या आप इस पर विस्तार से विचार करेंगे और शायद कुछ कोड जोड़ देंगे? – sharkin

0

मुझे नहीं लगता कि आपको इस तरह कचरा कलेक्टरों पर भरोसा करना चाहिए। भले ही आप कटौती करते हैं कि वे कैसे काम करते हैं, यह बहुत अच्छी तरह से हो सकता है कि अगली रिलीज में उन्होंने इसे फिर से कार्यान्वित किया है।

किसी भी मामले में, ऑब्जेक्ट्स को कचरा नहीं दिया जाता है जब आप उन्हें अव्यवस्थित करते हैं। आम तौर पर वे तब तक एकत्र किए जाते हैं जब तक कि कुछ सीमा तक नहीं पहुंच जाती है और फिर उन्हें रिहा कर दिया जाता है।

खासकर जावा कार्यक्रमों में यह बहुत ध्यान देने योग्य है जब आप कार्य प्रबंधक पर स्मृति खपत को देखते हैं। यह बढ़ता और बढ़ता है और अचानक हर मिनट यह फिर से गिर जाता है।

4

ऐसी कोई चीज नहीं है जो सी ++ - सी # में विनाशक की तरह है।(सी # में विनाशक की एक अलग अवधारणा है, जिसे फाइनलाइज़र भी कहा जाता है, जो सी ++ विनाशकों के समान वाक्यविन्यास का उपयोग करता है, लेकिन वे वस्तुओं को नष्ट करने के लिए असंबंधित हैं। वे अप्रबंधित संसाधनों के लिए क्लीनअप तंत्र प्रदान करना चाहते हैं।) कचरा संग्राहक को साफ़ करने के कुछ समय बाद संदर्भित किए जाएंगे। तुरंत नहीं, और इसकी गारंटी देने का कोई तरीका नहीं है।

सौभाग्य से कोई वास्तविक कारण नहीं है कि आप इसकी गारंटी क्यों देना चाहते हैं। अगर आपको स्मृति की आवश्यकता है, तो जीसी फिर इसे पुनः प्राप्त करेगा। यदि आप नहीं करते हैं, तो क्यों परवाह है कि अभी भी कुछ कचरा वस्तु है? यह एक स्मृति रिसाव नहीं है: जीसी अभी भी इसे पा सकता है और इसे किसी भी समय साफ कर सकता है।

4

नहीं, इसकी गारंटी नहीं है। जावा जैसे भाषाओं की तरह, सी # में कचरा कलेक्टर जब आवश्यक हो (i। ई। जब ढेर बहुत भरा हो रहा है) चलाता है। हालांकि, जब आपकी वस्तुएं IDisposable लागू करती हैं, i। ई। वे एक Dispose() विधि है और यह कहा जा तो आप using कीवर्ड का लाभ ले सकते है, जब कि using ब्लॉक छोड़ने

using (var foo = new DisposableObject()) { 
    // do something with that 
} 

इस तरह Dispose() तुरंत बुलाया जाएगा।

नोट: IDisposable कई प्रकारों में पाया जाता है, विशेष रूप से जीडीआई + लेकिन डेटाबेस कनेक्शन, लेनदेन इत्यादि। इसलिए यह वास्तव में सही पैटर्न हो सकता है।

नोट 2: ब्लॉक के ऊपर के दृश्य एक try/finally ब्लॉक में अनुवाद पीछे होगा मिल:

var foo = new DisposableObject(); 
try 
{ 
    // do something with that 
} 
finally 
{ 
    foo.Dispose(); 
} 

लेकिन उस अनुवाद संकलक द्वारा किया जाता है और बहुत आसान Dispose() कॉल करने के लिए भूल नहीं करने के लिए।

0

नहीं। यदि आप CLI विनिर्देश का उल्लेख (पी। Finalizers के बारे में 8.9.6.7) http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf आप पा सकते हैं निम्नलिखित

CLI यह सुनिश्चित करना चाहिए finalizers कहा जाता है कि बाद जल्द ही उदाहरण दुर्गम हो जाता है । जबकि ट्रिगर को अंतिम रूप देने के लिए स्मृति दबाव पर निर्भर स्वीकार्य है, इसको लागू करने, लेकिन अतिरिक्त मैट्रिक्स

के उपयोग पर विचार करना चाहिए यह नहीं करना चाहिए।

7

सं। ऑब्जेक्ट वास्तव में "दायरे से बाहर नहीं" जाता है, इसके संदर्भ में (यानी वे चर जो आप इसे एक्सेस करने के लिए उपयोग करते हैं) करता है।

एक बार किसी दिए गए ऑब्जेक्ट के संदर्भ में कोई संदर्भ नहीं है, तो वह वस्तु योग्य कचरा संग्रह (जीसी) के लिए आवश्यकता उत्पन्न होनी चाहिए। जब भी जीसी निर्णय लेता है कि उसे आपके नो-लॉन्ग-रेफरेंस ऑब्जेक्ट को रिक्त स्थान प्राप्त करने की आवश्यकता होती है, तब ऑब्जेक्ट फ़ाइनलाइज़र को कॉल किया जाएगा।

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

उदा। कुछ विलंब के लिए खेद है, था -


using (var conn = new DbConnection()) 
{ 
    // do stuff with conn 
} // conn.Dispose() is automatically called here. 

using ब्लॉक बस कुछ वाक्यात्मक चीनी जो, एक try ब्लॉक में conn वस्तु के साथ आपकी सहभागिता लपेटता एक finally ब्लॉक जो केवल कॉल conn.Dispose()

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