2013-02-26 11 views
6

Angenommen, eine Instanz von MyClass ist nicht auf eine andere Art und Weise verwurzelt, wird die private statische Referenz hier verhindern, dass sie als Garbage Collection erfasst wird?Kann eine Klasse, die sich selbst in einem statischen Feld referenziert, Müll gesammelt werden?

+1

mögliche Duplikate von [Werden statische Mitglieder jemals Müll gesammelt?] (Http://stackoverflow.com/questions/6600093/do-static-members-ever-get-garbage-collected) EDIT: Kurz gesagt, nein, Ich glaube nicht, dass es so sein wird. Zum Beispiel gibt es im Code, den Sie gepostet haben, keinen Grund, warum der öffentliche Konstruktor nicht hätte haben können: if (heldInstance == null) Andere als die _instances_, in denen die einzigen gehaltenen Referenzen von sich selbst _eventually_ gesammelt werden wenn der GC feststellt, dass er nicht mehr zugänglich ist. –

+0

Ja, sie werden gesammelt, kurz bevor die AppDomain entladen wird. Das ist belanglos, es sei denn, die Klasse hat einen Finalizer. –

+3

Die Tatsache, dass ein statisches Feld der Klasse auf eine Instanz * der gleichen Klasse * verweist, ist irrelevant. Statische Felder sind Wurzeln; Sie werden alles am Leben halten, was Sie unabhängig von ihrem Typ in sie stecken. –

Antwort

8

Die von Ihnen gepostete Klasse wird nicht als Müll gesammelt. Sie können dies testen, indem es einen Finalizer mit einer Konsolenausgabe geben:

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

    } 
} 

Der Ausgang wird sein:

END 
Finalizer called 

Was bedeutet, dass die Klasse erst in dem letzten Abrüsten der Anwendung gesammelt wird, nicht während einer normalen Speicherbereinigung.

Wenn Sie mehrere Instanzen dieser Klasse wie folgt zu erstellen:

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

dann alle außer der jüngsten wird Müll gesammelt werden.

Sie würden

Finalizer called 
Finalizer called 
Finalizer called 
END 
Finalizer called 
+1

Beachten Sie, dass dies nur gilt, weil 'heldInstance' statisch ist. Es ist nichts Besonderes an der Tatsache, dass eine Instanz von 'MyClass' einen Verweis auf sich selbst hat. Also, ja "eine Klasse, die sich selbst bezeichnet" kann Müll gesammelt werden. Die Klasse im Beispiel kann dies jedoch nicht. – dgvid

2

Der Garbage Collector bekommen bestimmt, welche Objekte erreichbar sind und diejenigen sammeln, die es nicht sind. Um festzustellen, ob ein Objekt erreichbar ist, beginnt der Kollektor mit den so genannten Wurzeln. Unter den Wurzeln sind die Dinge, die derzeit auf dem Auswertungsstapel sind, aber auch statische Felder. Der Kollektor folgt den Verweisen auf Objekte von den Wurzeln zu einem beliebigen Objekt und von einem solchen Objekt zu einem anderen Objekt und so weiter. Jedes Objekt, das auf diese Weise besucht wurde, ist erreichbar und wird daher am Leben erhalten.

In Ihrem Fall ist das statische Feld einer der Wurzeln des Garbage Collectors, und deshalb wird es nie irgendein Objekt sammeln, das (indirekt) von diesem Feld referenziert wird. Wenn Sie jedoch das Feld auf null festlegen, verweist dieses Feld nicht mehr auf die Instanz und die Instanz kann gesammelt werden.

Verwandte Themen