2013-02-26 144 views
6
public class MyClass { 
    private static MyClass heldInstance; 

    public MyClass() { 
    heldInstance = this; 
    } 
} 

MyClass का एक उदाहरण मानना ​​किसी अन्य तरीके से रूट नहीं है, क्या निजी स्थिर संदर्भ यहां कचरा होने से रोक देगा?क्या एक वर्ग जो स्थिर क्षेत्र में खुद को संदर्भित कर सकता है कचरा इकट्ठा किया जा सकता है?

+1

संभावित डुप्लिकेट [क्या स्थिर सदस्यों को कचरा इकट्ठा किया जाता है?] (Http://stackoverflow.com/questions/6600093/do-static-members-ever-get-garbage-collected) संपादित करें: संक्षेप में, नहीं, मुझे विश्वास नहीं है कि यह होगा। उदाहरण के लिए, आपके द्वारा पोस्ट किए गए कोड में, कोई कारण नहीं है कि सार्वजनिक कन्स्ट्रक्टर में 'if (heldInstance == null) नहीं हो सकता था, इसके अलावा, _instances_ जिसमें केवल एक ही संदर्भित संदर्भ स्वयं ही हैं, _eventually_ एकत्र किए जाएंगे जीसी द्वारा यह निर्धारित करता है कि यह अब सुलभ नहीं है। –

+0

हां, ऐपडोमेन को अनलोड किए जाने से ठीक पहले वे एकत्र हो जाते हैं। यह तब तक अपरिहार्य है जब तक कक्षा में फाइनलाइज़र नहीं होता है। –

+3

तथ्य यह है कि कक्षा का एक स्थिर क्षेत्र उसी वर्ग के उदाहरण * का संदर्भ दे रहा है * अप्रासंगिक है। स्थिर क्षेत्र जड़ें हैं; वे जीवित कुछ भी रखेंगे जो आपने उनके प्रकार के बावजूद रखे हैं। –

उत्तर

8

आपके द्वारा पोस्ट की गई कक्षा कचरा नहीं होगी। आप इसे एक सांत्वना उत्पादन के साथ एक finalizer देकर यह परीक्षण कर सकते हैं:

public class MyClass 
{ 
    private static MyClass heldInstance; 
    public MyClass() 
    { 
     heldInstance = this; 
    } 
    ~MyClass() 
    { 
     Console.WriteLine("Finalizer called"); 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     var x = new MyClass(); // object created 

     x = null; // object may be eliglible for garbage collection now 

     // theoretically, a GC could happen here, but probably not, with this little memory used 
     System.Threading.Thread.Sleep(5000); 

     // so we force a GC. Now all eligible objects will definitely be collected 
     GC.Collect(2,GCCollectionMode.Forced); 

     //however their finalizers will execute in a separate thread, so we wait for them to finish 
     GC.WaitForPendingFinalizers(); 

     System.Threading.Thread.Sleep(5000); 
     Console.WriteLine("END"); 

    } 
} 

उत्पादन होगा:

END 
Finalizer called 

जिसका मतलब है कि वर्ग केवल आवेदन की अंतिम टियरडाउन पर एकत्र हो जाता है, नहीं एक नियमित कचरा संग्रह के दौरान।

आप इस तरह इस वर्ग के कई उदाहरण बनाते हैं:

var x = new MyClass(); 
x = new MyClass(); 
x = new MyClass(); 
x = new MyClass(); 

तो सभी को छोड़कर हाल ही में एक कचरा एकत्र किया जाएगा।

आप मिलेगा

Finalizer called 
Finalizer called 
Finalizer called 
END 
Finalizer called 
+1

ध्यान दें कि यह केवल सत्य है क्योंकि 'आयोजित किया गया' स्थिर है। इस तथ्य के बारे में कुछ भी खास नहीं है कि 'MyClass' का एक उदाहरण स्वयं का संदर्भ है। तो, हां "एक वर्ग जो खुद को संदर्भित करता है" कचरा एकत्र किया जा सकता है। हालांकि, उदाहरण में कक्षा नहीं कर सकते हैं। – dgvid

2

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

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