कचरा संग्रहण से अलग करना महत्वपूर्ण है। वे पूरी तरह से अलग चीजें हैं, आम तौर पर एक बिंदु के साथ जो मैं एक मिनट में आऊंगा।
Dispose
, कचरा संग्रह और अंतिम रूप देना
जब आप एक using
बयान लिखते हैं , तो यह बस एक कोशिश के लिए सिंटैक्टिक शुगर होता है / अंत में ब्लॉक होता है Dispose
, जिसे तब भी कहा जाता है, भले ही using
बयान के शरीर में कोड एक अपवाद फेंकता हो। इसका अर्थ यह नहीं है कि ऑब्जेक्ट ब्लॉक के अंत में एकत्रित कचरा है।
निपटान अप्रबंधित संसाधनों (गैर-स्मृति संसाधनों) के बारे में है। ये यूआई हैंडल, नेटवर्क कनेक्शन, फ़ाइल हैंडल आदि हो सकते हैं। ये सीमित संसाधन हैं, इसलिए आप आम तौर पर इन्हें जल्द से जल्द जारी कर सकते हैं। IDisposable
जब भी आपका प्रकार एक अप्रबंधित संसाधन "सीधे" (आमतौर पर a IntPtr
) या अप्रत्यक्ष रूप से (जैसे a Stream
, a SqlConnection
आदि) के माध्यम से लागू होता है, तो आपको इसे लागू करना चाहिए ।
कचरा संग्रह केवल स्मृति के बारे में है - एक छोटे से मोड़ के साथ। कचरा संग्रहकर्ता उन वस्तुओं को खोजने में सक्षम है जिन्हें अब संदर्भित नहीं किया जा सकता है, और उन्हें मुक्त कर सकते हैं। यह हर समय कचरा नहीं दिखता है - केवल जब यह पता लगाता है कि इसे जरूरत है (जैसे कि एक "पीढ़ी" ढेर स्मृति से बाहर चलाता है)।
मोड़ अंतिम रूप देना है । कचरा संग्रहकर्ता उन वस्तुओं की एक सूची रखता है जो अब उपलब्ध नहीं हैं, लेकिन जिनके पास एक अंतिम रूप है ( ~Foo()
सी # में लिखा गया है, कुछ भ्रामक रूप से - वे सी ++ डिस्ट्रक्टर्स की तरह कुछ भी नहीं हैं)। यह इन वस्तुओं पर अंतिम रूप से चलता है, बस अगर उनकी स्मृति को मुक्त करने से पहले उन्हें अतिरिक्त सफाई करने की आवश्यकता होती है।
फ़ाइनलीज़र का उपयोग लगभग हमेशा संसाधनों को साफ़ करने के लिए किया जाता है, जहाँ टाइप का उपयोगकर्ता क्रमबद्ध तरीके से इसे निपटाना भूल गया हो। तो अगर आप एक खोलने FileStream
लेकिन भूल जाते हैं कॉल करने के लिए Dispose
या Close
, finalizer जाएगा अंत में आप के लिए अंतर्निहित फ़ाइल हैंडल को छोड़ दें। एक अच्छी तरह से लिखित कार्यक्रम में, अंतिम रूप से मेरे विचार में कभी भी आग नहीं लगनी चाहिए।
एक चर सेट करना null
एक चर सेट करने पर एक छोटा सा बिंदु null
- यह कचरा संग्रह के लिए लगभग कभी भी आवश्यक नहीं है। यदि आप एक सदस्य चर है, तो आप कभी-कभी इसे करना चाह सकते हैं, हालांकि मेरे अनुभव में किसी वस्तु के "भाग" के लिए यह दुर्लभ नहीं रह गया है। जब यह एक स्थानीय चर होता है, तो जेआईटी आमतौर पर स्मार्ट होता है (रिलीज मोड में) यह जानने के लिए कि आप फिर से एक संदर्भ का उपयोग नहीं करने जा रहे हैं। उदाहरण के लिए:
StringBuilder sb = new StringBuilder();
sb.Append("Foo");
string x = sb.ToString();
// The string and StringBuilder are already eligible
// for garbage collection here!
int y = 10;
DoSomething(y);
// These aren't helping at all!
x = null;
sb = null;
// Assume that x and sb aren't used here
एक समय जहां यह स्थानीय चर सेट करने के लायक हो सकता null
है जब आप लूप में होते हैं, और लूप की कुछ शाखाओं को चर का उपयोग करने की आवश्यकता होती है, लेकिन आप जानते हैं कि आप उस बिंदु पर पहुंच गए हैं जिस पर आप नहीं हैं। उदाहरण के लिए:
SomeObject foo = new SomeObject();
for (int i=0; i < 100000; i++)
{
if (i == 5)
{
foo.DoSomething();
// We're not going to need it again, but the JIT
// wouldn't spot that
foo = null;
}
else
{
// Some other code
}
}
आईडीआईएसओपी / फाइनल को लागू करना
तो, क्या आपके अपने प्रकारों को अंतिम रूप देना चाहिए? लगभग निश्चित रूप से नहीं। यदि आप अप्रत्यक्ष रूप से अप्रबंधित संसाधनों को रखते हैं (जैसे कि आपको FileStream
एक सदस्य चर के रूप में मिला है ) तो अपने स्वयं के अंतिम रूप को जोड़ने से कोई मदद नहीं मिलेगी: धारा लगभग निश्चित रूप से कचरा संग्रह के लिए योग्य होगी जब आपकी वस्तु होगी, इसलिए आप बस भरोसा कर सकते हैं FileStream
फ़ाइनलीज़र होना (यदि आवश्यक हो - यह किसी और चीज़ आदि को संदर्भित कर सकता है)। आप एक अप्रबंधित संसाधन धारण करने के लिए चाहते हैं "लगभग" सीधे, SafeHandle
अपने दोस्त है - यह समय के साथ जा रहा प्राप्त करने के लिए का एक सा लगता है, लेकिन यह आप लगाएंगे लगभग एक finalizer फिर से लिखने की ज़रूरत कभी नहीं । यदि आप किसी संसाधन (क IntPtr
) पर वास्तव में प्रत्यक्ष नियंत्रण रखते हैं, तो आपको आम तौर पर केवल एक फाइनल की आवश्यकता होती है और आपको आगे बढ़ना चाहिएSafeHandle
जितनी जल्दी आप कर सकते हों। (वहां दो लिंक हैं - दोनों पढ़ें, आदर्श रूप से।)
जो डफी के पास फ़ाइनलीज़र और आईडीसॉफ़ेरियल के आसपास दिशानिर्देशों का एक बहुत लंबा सेट है (स्मार्ट लोक के बहुत से सह-लिखित) जो पढ़ने लायक हैं। यह ध्यान देने योग्य है कि यदि आप अपनी कक्षाओं को सील करते हैं, तो यह जीवन को बहुत आसान बना देता है: Dispose
एक नई आभासी Dispose(bool)
विधि आदि को ओवरराइड करने का पैटर्न केवल तब प्रासंगिक होता है जब आपकी कक्षा विरासत के लिए डिज़ाइन की गई हो।
यह एक छोटा सा रहा है, लेकिन कृपया स्पष्टीकरण के लिए पूछें कि आप कुछ कहाँ चाहेंगे :)