public class MyClass {
private static MyClass heldInstance;
public MyClass() {
heldInstance = this;
}
}
MyClassのインスタンスが他の方法でルート化されていないと仮定すると、ここでのプライベート静的参照は、ガベージコレクションを防ぎますか?
public class MyClass {
private static MyClass heldInstance;
public MyClass() {
heldInstance = this;
}
}
MyClassのインスタンスが他の方法でルート化されていないと仮定すると、ここでのプライベート静的参照は、ガベージコレクションを防ぎますか?
投稿したクラスはガベージコレクションされません。これをテストするには、コンソール出力を備えたファイナライザーを指定します。
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
ガベージ コレクターは、到達可能なオブジェクトを判断し、そうでないオブジェクトを収集します。オブジェクトが到達可能かどうかを判断するために、コレクターはいわゆるrootsから開始します。ルートの中には、現在評価スタックにあるものだけでなく、静的フィールドもあります。コレクターは、ルートから任意のオブジェクトへのオブジェクトへの参照、およびそのようなオブジェクトから他のオブジェクトへの参照などをたどります。この方法でアクセスされた各オブジェクトは到達可能であるため、存続します。
あなたの場合、静的フィールドはガベージ コレクターのルートの 1 つであるため、そのフィールドによって (間接的に) 参照されるオブジェクトを収集することはありません。ただし、フィールドを に設定するとnull
、そのフィールドはインスタンスを参照しなくなり、インスタンスが収集される可能性があります。