これは、C#/。NETでのオブジェクトのファイナライズと収集に関する学術的な質問です。背景の読み方は、C#言語仕様の自動メモリ管理のセクション3.9です。
オブジェクトへの明示的な参照がない場合、ガベージコレクションになる可能性があります。「破壊対象」になります。将来のある時点で(たとえば、ガベージコレクションを強制する場合)、オブジェクトのデストラクタが実行されます。
デストラクタで、オブジェクトへの参照を保存すると、オブジェクトはファイナライズされますが、収集の対象にはなりません。これにより、オブジェクトはファイナライズされたが収集されていない状態になる可能性があります。仕様のセクション3.9には、この例があります。
この時点では、オブジェクトはまだガベージコレクションされていないため、実際にはまだ生きています。ただし、オブジェクトを参照するWeakReferenceは、オブジェクトが収集されたことを示すfalseのIsAlive値を報告します。
中心的な質問はこれです-IsAliveプロパティは実際に何を報告していますか?このプロパティの値は、読み取った直後にfalseになる可能性があるため、trueの値を信頼できないことはわかっています。ただし、falseの値は信頼できるものであり、(ドキュメントによると)オブジェクトがガベージコレクションされたことを示すことを意味します。では、この場合、IsAliveプロパティは何を示しているのでしょうか。オブジェクトはファイナライズされているが収集されていない状態であると考えられるため、オブジェクトがガベージコレクションされているかどうかは厳密ではありません。
これが動作を示すサンプルです。
public class Dog
{
public static Dog KeepDogRef;
public string Name { get; set; }
public Dog(string name)
{
Name = name;
}
~Dog()
{
Console.WriteLine("Dog destructor for " + Name + " called");
Dog.KeepDogRef = this;
}
public void Bark()
{
Console.WriteLine(Name + " : Woof");
}
}
そしてメインプログラムのコード。コードを実行すると、オブジェクトを再構成した後でも、元のWeakReferenceがIsAliveをfalseとして報告することがわかります。
static void Main()
{
Dog dog = new Dog("Bowser");
WeakReference dogRef = new WeakReference(dog);
// Unref Bowser, now eligible for destruction
dog = null;
GC.Collect();
GC.WaitForPendingFinalizers();
// Bowser no longer alive
Console.WriteLine(string.Format("Object still alive: {0}", dogRef.IsAlive));
// Bowser alive again
Dog newRef = Dog.KeepDogRef;
newRef.Bark();
}
}