1. 程式人生 > >C#中的弱引用(WeakReference

C#中的弱引用(WeakReference

Object obj = new Object();
WeakReference wref = new WeakReference( obj );
obj = null;

第一行程式碼新建了一個新的物件,這裡叫它物件A,obj是對物件A的強引用。接著第二行程式碼新建了一個弱引用物件,引數就是物件A的強引用,第三行程式碼釋放掉對物件A的強引用。這時如果GC進行回收,物件A就會被回收。
怎樣在取得物件A的強引用呢?很簡單,請看程式碼2:

Object obj2 = wref.Target;
if( obj2 != null )
{
   // 做你想做的事吧。
}
else
{
// 物件已經被回收,如果要用必須新建一個。
}

只要顯示的將弱引用的Target屬性附值就會得到弱引用所代表物件的一個強引用。不過在使用物件之前要對其可用性進行檢查,因為它可能已經被回收了。如 果你得到的是null(VB.NET下為Nothing),表明物件已經被回收,不能再用了,需要重新分配一個。如果不是null,就可以放心大膽的用 了。
接下來讓我們看WeakReference的另外一個版本,請看程式碼3:
// public WeakReference(
//   object target,
//   bool trackResurrection
//);


Object obj1 = new Object();

Object obj2 = new Object();

WeakReference wref1 = new WeakReference( obj1, false );

WeakReference wref2 = new WeakReference( obj2, true );

WeakReference的另外一個版本有兩個引數,第一個引數和我們前面用的版本的一樣。第二個引數讓我們看一下他的原型,bool trackResurrection,跟蹤復活,是個bool型,就是是否跟蹤復活。前面的文章中我提到過需要Finalize的物件在最終釋放前會有一 次復活,我們大概可以猜到第二個引數表示的意思了。如果我們第二個引數給false,這個弱引用就是一個short weak reference(短弱引用),當GC回收時,發現根中沒有這個物件的引用了,就認為這個物件無用,這時短弱引用對這個物件的跟蹤到此為止,弱引用的 Target被設定為null。前面的一個引數的建構函式版本新建的弱引用為短弱引用。如果第二個引數給true,這個弱引用就是一個long weak reference(長弱引用)。在物件的Finalize方法沒有被執行以前,Target都可用。不過這是物件的某些成員變數也許已經被回收,所以使 用起來要想當小心。
現在讓我們看看WeakReference是如何實現的。很顯然WeakReference不能直接的引用目標物件,WeakReference的 Target屬性的get/set是兩個函式,從某處查到目標物件的引用返回,而不是我們最常用寫的那樣直接返回或者設定一個私有變數。GC維護了兩個列 表來跟蹤兩種弱引用的目標物件,在一個 WeakReference物件建立時,它在相應的列表中找到一個位置,將目標物件的引用放入,很顯然,這兩個列表不是根的一部分。在GC進行記憶體回收的 時候,如果要回收某一個物件,會檢查弱引用的列表,如果儲存著這個物件的引用,則將其設為null。 public class AspPage : Page
{
private static ArrayList __ENCList = new ArrayList();

   [DebuggerNonUserCode]
        public AspPage()
        {
            base.Load += new EventHandler(this.Page_Load);
            ArrayList list = __ENCList;
            lock (list)
            {
                __ENCList.Add(new WeakReference(this));
            }
        }