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

    public MyClass() { 
    heldInstance = this; 
    } 
} 

Zakładając, że instancja MyClass nie jest zrootowana w inny sposób, czy prywatne odniesienie statyczne uniemożliwi jej zbieranie śmieci?Czy klasa, która odwołuje się do siebie w polu statycznym, może być zbiorem śmieci?

+1

możliwy duplikat [Czy statyczni członkowie kiedykolwiek otrzymają śmieci zebrane?] (Http://stackoverflow.com/questions/6600093/do-static-members-ever-get-garbage-collected) EDYCJA: W skrócie, nie, Nie wierzę, że tak będzie. Na przykład w opublikowanym przez ciebie kodzie nie ma powodu, dla którego publiczny konstruktor nie mógłby mieć wartości 'if (heldInstance == null)' Poza tym, _instancje_, w których tylko przechowywane odwołania są od siebie do siebie, będą automatycznie zbierane przez GC, gdy ustali, że nie jest już dostępna. –

+0

Tak, są zbierane tuż przed wyładowaniem AppDomain. To nie ma znaczenia, chyba że klasa ma finalizatora. –

+3

Fakt, że pole statyczne klasy odwołuje się do instancji * tej samej klasy *, nie ma znaczenia. Pola statyczne są korzeniami; zachowają przy życiu wszystko, co w nich włożysz, bez względu na jego typ. –

Odpowiedz

8

Zaksięgowana klasa nie zostanie zebrana. Można to sprawdzić poprzez nadanie mu finalizatora z wyjścia konsoli:

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"); 

    } 
} 

wyjście będzie:

END 
Finalizer called 

co oznacza, że ​​klasa dostaje tylko zebrane w końcowym przerywaniem wniosku, nie podczas zwykłego zbierania śmieci.

Jeśli utworzyć wiele instancji tej klasy tak:

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

wtedy wszystko z wyjątkiem najnowszego jeden śmieci będą zbierane.

co można uzyskać

Finalizer called 
Finalizer called 
Finalizer called 
END 
Finalizer called 
+1

Należy zauważyć, że jest to prawdą tylko dlatego, że 'heldInstance' jest statyczne. Nie ma nic szczególnego w tym, że instancja 'MyClass' ma odniesienie do samej siebie. Tak więc "klasa, która się odwołuje" może być zbiorem śmieci. Jednak klasa w tym przykładzie nie może. – dgvid

2

Kolektor śmieci określa, które obiekty są nieosiągalnego i będzie zbierać te, które nie są. Aby ustalić, czy obiekt jest osiągalny, kolektor rozpocznie pracę z tak zwanymi korzeniami. Wśród źródeł są rzeczy obecne na stosie ewaluacji, ale także statyczne pola . Kolektor będzie podążał za odniesieniami do obiektów od korzeni do dowolnego obiektu, od takiego obiektu do dowolnego innego obiektu i tak dalej. Każdy obiekt, który został odwiedzony w ten sposób, jest osiągalny i dlatego będzie utrzymywany przy życiu.

W twoim przypadku pole statyczne jest jednym z korzeni garbage collector i dlatego nigdy nie będzie zbierać żadnego obiektu, który jest przywoływany (pośrednio) przez to pole. Jeśli jednak ustawisz to pole na null, to pole nie będzie już odwoływać się do instancji, a instancja może być gromadzona.

Powiązane problemy