System.WeakReferenceクラスは弱い参照を表すクラスです。
このクラスはガベージコレクトと関わっていまして
通常、ガベージコレクトが発生した際ピープにあるオブジェクト
達が掃除されるのですが、どこかに一つでも参照が保持されている
場合は、ガベージコレクトの対象にはなりません。
これを強い参照といいます。まあ、通常の参照の状態です。
で、これだとまずいケースがたまにあります。
大量のデータを一括して処理するバッチ処理とかが当てはまるでしょうか。
そのような処理の場合、大抵リストなり辞書なりを用いて処理をしたりします。
ずっとリストなどにオブジェクトをため続けた場合、メモリ不足してしまう
パターンもあったりします。(作り方がまずいって言えばそれまでなんですが・・・)
メモリが枯渇しだしてくるとGCが走りますが、参照がリスト内に存在している限り
オブジェクトは廃棄されません。
そんなときの場合に、System.WeakReferenceを使ったりするときがあります。
このオブジェクトは、内部にターゲットとなるオブジェクトの参照を一つ持ちます。
通常、先ほど記述したように参照が保持されている限りオブジェクトはGCされないのですが
このクラスの場合は、ガベージコレクトの対象としてマークされます。
実際、開発してる際にこのクラスを使うことは少ないと思います。
私の場合は、javaの方ですが一回しか使ったことないです・・。
どちらかと言うと、フレームワークを作成したりする場合の方が結構使うと思います。
こんなわけであんまり自分自身も分かってないですが、とりあえずサンプル。
using System; using Gsf.Research.ClassLibrary; namespace Gsf.Research.ClassLibrary.System{ /// <summary> /// System.WeakReferenceクラスのサンプルです。 /// </summary> /// <remarks> /// System.WeakReferenceクラスは弱い参照を表します。 /// 弱い参照とは、参照を保持しているけれどもガベージコレクトの /// 対象となる参照の事です。 /// 通常の参照(強い参照)の場合は、自身のスコープが抜けても /// どこかで参照が保持されている場合、ガベージコレクトの /// 対象にはなりませんが、WeakReferenceを利用した場合は /// その場合もガベージコレクトの対象となります。 /// 基本的なイメージは, javaの場合でいうとjava.lang.ref.WeakReferenceクラスと /// 同じです。 /// /// 以下の2つのプロパティを主に使用します。 /// -IsAlive --> 内部で保持している参照が生存しているかどうか /// -Target --> 内部で保持する参照を取得・設定します /// /// </remarks> public class WeakReferenceResearch00 : IExecutable{ /// <summary> /// サンプルデータクラスです。 /// </summary> class A{ public string name; public override string ToString(){ return name; } } //////////////////////////////////////////////////////////////// // 検証を行うため、2つのフィールドを用意。 // 一つは、そのままの強い参照(_a2), もう一つは弱い参照(_wr) // A _a2; WeakReference _wr; /// <summary> /// 処理を実行します。 /// </summary> public void Execute(){ WeakReferenceResearch00 w = new WeakReferenceResearch00(); w.Execute1(); w.Execute2(); } void Execute1(){ // // _a2, _wrともに、ローカルスコープで // 生成したオブジェクトの参照を持つ。 // A a = new A(); A a2 = new A(); a.name = "hoge"; a2.name = "hoge2"; _wr = new WeakReference(a); _a2 = a2; Console.WriteLine("Execute1() _a2={0}", _a2); Console.WriteLine("Execute1() _wr.IsAlive={0}", _wr.IsAlive); Console.WriteLine("Execute1() _wr.Target={0}", _wr.Target); // // [注意]その変数自身が存在しているスコープにいる場合は、 // WeakReferenceを使っていてもガベージコレクトされません。 // } void Execute2(){ // 強制ガベージコレクト // // この時点で、_wrの保持している参照が廃棄されます。 GC.Collect(); // // _a2(強い参照)は先ほどの参照を保持しているが、 // _wr(弱い参照)はGCにかかり、廃棄されている。 // Console.WriteLine("Execute2() _a2={0}", _a2); Console.WriteLine("Execute2() _wr.IsAlive={0}", _wr.IsAlive); Console.WriteLine("Execute2() _wr.Target={0}", _wr.Target); } } }
ちなみに、javaの場合も同じようなクラスがありまして
java.lang.ref.WeakReference java.lang.ref.SoftReference java.lang.ref.PhantomReference java.util.WeakHashMap
などというクラスが存在しています。
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場