[C#] C#編寫事件或委託時如果處理不好會造成內存泄漏

 用C#編寫事件或委託時如果處理不好會造成內存泄漏,看下面代碼:



public class DoA2EventArgs : EventArgs
{
}


public class ClassA
{
public delegate void DoAEventHandler( object sender, EventArgs e);
public event EventHandler < DoA2EventArgs > DoA2EventHandler;
public DoAEventHandler DoAEvent;

protected void OnDoA2Event(DoA2EventArgs args)
{
EventHandler < DoA2EventArgs > handler = DoA2EventHandler;

if (handler != null )
{
handler( this , args);
}
}

public void DoA()
{
if (DoAEvent != null )
{
DoAEvent( this , new EventArgs());
}
}

public void DoA2()
{
OnDoA2Event( new DoA2EventArgs());
}

~ ClassA()
{
Console.WriteLine( " Class A Finished! " );
}
}

public class ClassB
{
ClassA a;

public ClassB()
{
a = new ClassA();
a.DoAEvent = DoA;
}

public void DoA( object sender, EventArgs e)
{
}

~ ClassB()
{
Console.WriteLine( " Class B Finished! " );
}
}




如果我們做如下實現



ClassB b = new ClassB();
ClassA a = new ClassA();
a.DoAEvent = b.DoA;
a.DoA2EventHandler += new EventHandler < DoA2EventArgs > (b.DoA2);
b = null ;

GC.Collect();



這是我們會發現,雖然對象b已經被賦值爲空,但對象並沒有被GC回收掉。原因是a對象還存在,同時a對象的DoAEvent

和 DoA2EventHandler 引用了b對象。

要將b回收掉我們可以做如下操作

一種方式是將a回收掉

a = null;

b = null;

這樣 b 就回收掉了。

如果不想把a回收掉則

a.DoAEvent = null ;
a.DoA2EventHandler -= b.DoA2;



還有一點要提一下的是

ClassB 類內部申明的 ClassA 對象,如果事件委託指向ClassB 對象本身,則不需要額外做操作,b = null; 時

ClassB 和 ClassA 實例都會自動回收。

發佈了42 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章