オブジェクトクラスのデリゲートメソッドでクラスを使用するWeakReference
と、オブジェクトクラスはGCによって収集されますが、それの別のコピーがWeakReference
?に存在しているように見えます。
言葉で説明するのは難しいと思います。例を挙げましょう。私は次のオブジェクトクラスを持っていますTestObject
:
class TestObject
{
public string message = "";
private delegate string deleg();
public TestObject(string msg)
{
message = msg;
}
public Delegate GetMethod()
{
deleg tmp = this.TestMethod;
return tmp;
}
public string TestMethod()
{
return message;
}
}
今、私のメインアプリケーションでは、を介してメソッドを参照しようとしTestMethod
てTestObject
いWeakReference
ます。意図はTestObject
、すべてのハード参照がなくなったときにGCによって収集できるようにすることです。これは私のメインアプリケーションがどのように見えるかです:
static void Main(string[] args)
{
var list = new List<WeakReference>();
var obj = new TestObject("Hello 1");
list.Add(new WeakReference(obj.GetMethod()));
Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke()); //Works fine
obj = null; //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC
GC.Collect(); //Force GC
Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False"));
Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke());
Console.ReadKey();
}
上記のコードを実行したときの出力は次のとおりです。
これが奇妙なことです。最初の行では、初期化されたばかりで、への参照を保持していたため、obj
印刷できました。すべて正しい。次に、withに設定し、GCを強制的に収集しました。したがって、出力の2行目では、はnullになります。最後に、最後の行で、GCが離れて収集したので、出力にaをスローするか、何も出力しないことを期待しています。ただし、実際には出力の最初の行と同じものが出力されます。この時点でGCによって収集されるべきではありませんか?!"Hello 1"
obj
TestObject
obj
null
obj = null
obj
true
obj
NullReferenceException
TestObject
これは、objをnullに設定した後TestObject
、最初に保持されたものが後でGCによって収集されたかどうかという疑問を投げかけます。obj
オブジェクト全体をに渡した場合WeakReference
、つまり、new WeakReference(obj)
デリゲートをに渡すのではなく、に渡した場合はWeakReference
、完全に機能します。
残念ながら、私のコードではWeakReference
、デリゲートに渡す必要があります。WeakReference
GCがデリゲートを参照するだけでオブジェクトを収集できるように、を正しく機能させるにはどうすればよいですか?