C#の参照はオブジェクトを保持している変数がある限り、ガーベッジコレクトされることはありません。こういう参照は強い参照と呼ばれます。WeakReferenceの参照はそれを保持していても、他の強い参照がない限りガーベッジコレクトされます。
WeakReferenceにはShortとLongがありますが、ここではShortのみ考えます。
アプリケーションがモードレスなダイアログ(メッセージボックスのようなOKを押さない限り次に進めないものをモーダルダイアログといい、そうでないのをモードレスといいます)をいくつも作り、それを配列に格納したいとします。普通の配列やコレクションを使うと、参照は強い参照になるので、このダイアログが閉じられても参照を保持し続けガーベッジコレクトされることはありません。これをWeakReferenceの配列として持てば閉じられたダイアログはガーベッジコレクトされ、メモリの節約になるかもしれません。
まずアプリケーションのメインフォームのメンバーにWeakReferenceのListを加えます。
1 |
List<WeakReference> pds_ = new List<WeakReference>(); |
アプリケーションがモードレスダイアログをつくって、このリストにWeakReferenceを追加します。
1 2 3 |
PostDialog pd = new PostDialog(); pd.show(); pds_.Add(new WeakReference(pd)); |
WeakReferenceのコンストラクタに渡したオブジェクトは他の強い参照がなくなればガーベッジコレクトされます。
Listから列挙
1 2 3 4 5 6 7 8 |
foreach (WeakReference wr in pds_) { PostDialog pd = (PostDialog)wr.Target; if (pd != null && !pd.IsDisposed) { pd.DoSomething(); } } |
WeakReferenceのTargetがすでにガーベッジコレクトされている場合はnullが返ります。ただしオブジェクトがガーベッジコレクトされるかは定かではありませんのでタイミングには注意が必要と思われます。それと、ガーベッジコレクトされてもWeakReferenceオブジェクト自体は消えませんので上記のようなやり方でずっとやると、Listがどんどん大きくなっていってしまいます。