天天看點

面試之C#--垃圾回收器什麼時候回收?

每個對象隻有在該對象不存在任何引用才會被垃圾回收起回收。

可以調用靜态方法System.GC.Collect()垃圾回收器,但是不建議這麼做;

用using語句可以有效的自動釋放掉資源。

實在沒有辦法才用從析構函數中調用Dispose方法。

class Example:IDisposable

~example(){

Dispose();

}

public virtual void Dispose();

{

if(!this.disposed){

try{

//在此釋放稀缺資源

finally{

this.disposed=true;

GC.SuppressFinalize(this);

public void SomeBehavior()//示例方法

checkifdisposed();

...

private void checkifdisposed(){

if(this.disposed)

throw new ObjectDisposedException("Example");

private Resource scarce;

private bool disposed=false;

---------------------------------------------------------------------------------------------------------------------

附加C#垃圾回收器的分級回收機制:

C#中的回收器是分代的垃圾回收器(Gererational Garbage Collector) 它将配置設定的對象分為3個類别或代。(可用GC.GetGeneration方法傳回任意作為參數的對象目前所處的代)最近被配置設定記憶體的對象被放置于第0代,因為第0代很小,小到足以放進處理器的二級(L2)緩存,是以它能夠提供對對象的快速存取。經過一輪垃圾回收後,仍然保留在第

0代中的對象被移進第1代中,再經過一輪垃圾記憶體回收後,仍然保留在第1代中的對象則被移進第2代中,第2代中包含了生存期較長的對象。

在C#中值類型是在堆棧中配置設定記憶體,它們有自身的生命周期,是以不用對它們進行管理,會自動配置設定和釋放。而引用類型是在堆中配置設定記憶體的。

是以它的配置設定和釋放就需要像回收機制來管理。

C#為一個對象配置設定記憶體時,托管堆可以立即傳回新對象所需的記憶體,因為托管堆類似于簡單的位元組數組,有一個指向第一個可用記憶體空間的指針,

指針像遊标一樣向後移動,一段段記憶體就配置設定給了正在運作的程式的對象。

在不需要太多垃圾回收的程式小,托管堆性能優于傳統的堆。

當第0代中沒有可以配置設定的有效記憶體時,就觸發了第0代中的一輪垃圾回收,它将删除那些不再被引用的對象,并将目前正在使用的對象移至第1代。而當第0代垃圾回收後依然不能請求到充足的記憶體時,就啟動第1代垃圾回收。如果對各代都進行了垃圾回收後仍沒有可用的記憶體就會引發一個OutOfMemoryException異常。

終結器

在有些情況下,類可以提供一個終結器在對象被銷毀時執行,終結器是一個名為

Finalize的受保護的方法:

protected void Finalize()

base.Finalize();

//

釋放外部資源

垃圾回收器使用名為“終止隊列”的内部結構跟蹤具有

Finalize

方法的對象。每次您的應用程式建立具有Finalize 方法的對象時,垃圾回收器都在終止隊列中放置一個指向該對象的項。

托管堆中所有需要在垃圾回收器回收其記憶體之前調用它們的終止代碼的對象都在終止隊列中含有項。(實作Finalize 方法或析構函數對性能可能會有負面影響,是以應避免不必要地使用它們。用Finalize 方法回收對象使用的記憶體需要至少兩次垃圾回收。當垃圾回收器執行回收時,它隻回收沒有終結器的不可通路對象的記憶體。

這時,它不能回收具有終結器的不可通路對象。它改為将這些對象的項從終止隊列中移除并将它們放置在标為準備終止的對象清單中。該清單中的項指向托管堆中準備被調用其終止代碼的對象。垃圾回收器為此清單中的對象調用Finalize 方法,然後,将這些項從清單中移除。後來的垃圾回收将确定終止的對象确實是垃圾,因為标為準備終止對象的清單中的項不再指向它們。在後來的垃圾回收中,實際上回收了對象的記憶體。)

Dispose方法

在不使用終結器時,可以考慮使用Dispose方法,你可以使用這個方法來釋放所儲存包括的在托管對象引用在内的任何資源。但使用它時需用

GC.SuppressFinalize

來告知運作時這些對

象不需要終結。如下所示

:

public void Dispose()

object.Dispose();

dbConnection.Dispose();

GC.SuppressFinalize(this); //

申明不需要終結

建立并使用了Dispose方法的對象,就需要使用完該對象之後調用這些方法,最好是在Finally中調用。

以下代碼示範來自

MSDN

// Design pattern for the base class.

// By implementing IDisposable, you are announcing that instances

// of this type allocate scarce resources.

public class BaseResource : IDisposable

// Pointer to an external unmanaged resource.

private IntPtr handle;

// Other managed resource this class uses.

private Component Components;

// Track whether Dispose has been called.

private bool disposed = false;

// Constructor for the BaseResource object.

public BaseResource()

// Insert appropriate constructor code here.

// Implement IDisposable.

// Do not make this method virtual.

// A derived class should not be able to override this method.

Dispose(true);

// Take yourself off the Finalization queue

// to prevent finalization code for this object

// from executing a second time.

// Dispose(bool disposing) executes in two distinct scenarios.

// If disposing equals true, the method has been called directly

// or indirectly by a user's code. Managed and unmanaged resources

// can be disposed.

// If disposing equals false, the method has been called by the

// runtime from inside the finalizer and you should not reference

// other objects. Only unmanaged resources can be disposed.

protected virtual void Dispose(bool disposing)

// Check to see if Dispose has already been called.

if (!this.disposed)

// If disposing equals true, dispose all managed

// and unmanaged resources.

if (disposing)

// Dispose managed resources.

Components.Dispose();

// Release unmanaged resources. If disposing is false,

// only the following code is executed.

CloseHandle(handle);

handle = IntPtr.Zero;

// Note that this is not thread safe.

// Another thread could start disposing the object

// after the managed resources are disposed,

// but before the disposed flag is set to true.

// If thread safety is necessary, it must be

// implemented by the client.

disposed = true;

// Use C# destructor syntax for finalization code.

// This destructor will run only if the Dispose method

// does not get called.

// It gives your base class the opportunity to finalize.

// Do not provide destructors in types derived from this class.

~BaseResource()

// Do not re-create Dispose clean-up code here.

// Calling Dispose(false) is optimal in terms of

// readability and maintainability.

Dispose(false);

// Allow your Dispose method to be called multiple times,

// but throw an exception if the object has been disposed.

// Whenever you do something with this class,

// check to see if it has been disposed.

public void DoSomething()

if (this.disposed)