2014-01-24 54 views
1

我有一堆WindowsImpersonationContext對象,它們是IDisposable類型。現在考慮這兩個操作:應該手動處理存儲在集合中的IDisposable對象嗎?

Stack<WindowsImpersonationContext> stack = new Stack<WindowsImpersonationContext>(); 

public void BeginOperation() 
{ 
    // Push object to stack 
    var context = WindowsIdentity.Impersonate(...); 
    stack.Push(context); 
} 

public void EndOperation() 
{ 
    // Pop object from stack. 
    if (stack.Count != 0) 
    { 
     var context = stack.Pop(); 
     ... do various stuff with 'context' ... 
     context.Dispose(); // should this be called once the object is not needed anymore? 
    } 
} 

要我打電話Dispose()如果手動我不想等待GC做呢?如果我是100%沒有其他代碼會嘗試使用堆棧中引用的對象是否安全?更確切地說,如果我沒有明確地調用context.Dispose(),我假定即使在執行從EndOperation()返回後,我仍然處在GC的處置資源的情況下,儘管它沒有被引用不再是堆棧了?我的推理是否正確?

另外,使用上面的代碼,聲稱在執行下面一組操作後,堆棧將根據佔用的資源結束爲空(即,它用於包含的所有對象都放置在最後,我也不需要擔心其他地方處置什麼了):

BeginOperation(); 
    BeginOperation(); 
    EndOperation(); 
EndOperation(); 

編輯:我知道using可以/應該用於安全目的,但主要是我關心的是怎麼回事無論使用哪種語法,收集/ GC的背景...

回答

2

如果你不需要它了,它實現IDisposable使用using語句來。

// System.Collections.Stack 
public virtual object Pop() 
{ 
    if (this._size == 0) 
    { 
     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack")); 
    } 
    this._version++; 
    object result = this._array[--this._size]; 
    this._array[this._size] = null; 
    return result; 
} 

所以你看到有Pop後沒有在堆棧中再參考:

public void EndOperation() 
{ 
    // Pop object from stack. 
    if (stack.Count != 0) 
    { 
     using(var context = stack.Pop()) 
     { 
      // ... do various stuff with 'context' ... 
     } 
    } 
} 

除此之外Stack.Pop以這種方式(ILSPy,.NET 4)來實現。

一般而言,只要您使用非託管資源,您應該使用using(或try-finally)。通過這種方式可以確保即使錯誤地處理它們也是如此。

2

如果您確定除堆棧外沒有其他東西引用該對象,則是:您應該手動處置它。

我會改變你的代碼看起來更象這樣:

public void EndOperation() 
{ 
    // Pop object from stack. 
    if (stack.Count != 0) 
    { 
     using (var context = stack.Pop()) 
     { 
      ... do various stuff with 'context' ... 
     } 
    } 
} 

即使在「做不同的東西」塊發生異常,將被安置的方式。

如果你不自己處理它,那麼你依賴於正在處理的類的終結器 - 即使實現了終結器,它也可能被稱爲太晚了(想象如果它是一個打開的文件句柄)。

1

您可以使用using聲明,但你應該實現IDisposable之前。

相關問題