2015-09-08 45 views
2

我正在使用繼承並試圖理解使用IDisposable的最佳方式。下面是我的基類的一個例子。通過繼承使用IDisposable

我明白,如果我有一個類(讓在MyChild調用),從MyBase類繼承即使MyChild沒有實現IDisposable,如果MyChild被初始化Dispose方法將被執行(相信我說是正確的這)如果使用方法如下,

using(MyChild chl = new MyChild) {// some code}; 

我想雖然知道什麼是說我在MyChild類的對象,我要確保被處置。我是否必須實現IDisposable接口,並具有與MyBase類中相同的代碼,還是可以使用MyBase類中的代碼?我猜這就是爲什麼MyBase類中有一個受保護的虛擬Dispose方法?

我的基類

public class MyBase : IDisposable 
{ 
     // variables & methods declared here etc 

     public void Dispose() 
     { 
      Dispose(true); 
     } 

     protected virtual void Dispose(bool disposing) 
     { 
      if (disposing) 
      { 
       if (myObj != null) releaseObject(myObj); 
      } 
     } 

     private static void releaseObject(object obj) 
     { 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); 
     } 
} 

回答

5

void Dispose(bool disposing)protected virtual的一個原因。您打算覆蓋它(並調用基本版本)。

public class MyChild : MyBase 
{ 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      // Dispose Child's objects 
     } 

     base.Dispose(disposing); 
    } 
} 
3

你只需要重寫在子類中的方法Dispose(bool)添加任何你想要的其他處置。

然而,這是側步,真正的問題 - 你正在做的是有點不必要的,那種危險dangerous

這裏的教訓是:如果你會打電話給「元帥。 ReleaseComObject「,你能100%確定沒有其他託管代碼仍然可以訪問RCW嗎?如果答案是「否」,那麼不要叫它。最安全(最安全)的建議是完全避免Marshal.ReleaseComObject在一個系統中,在這個系統中,組件可以隨着時間的推移重新使用和版本化。

COM包裝器爲您構建的.NET是安全和可管理的,除非絕對必要,否則應該避免任何顯式處置。即使是Marshal.ReleaseComObject文件給出了幾個很好的理由來避免這種情況:如果RCW釋放時的RCW呼叫正在執行,可能會出現

更嚴重的錯誤。在這種情況下,進行調用的線程很可能會導致訪問衝突。但是,進程內存可能會損壞,並且進程可能會繼續運行,直到出現故障,原因很難調試。

...

因此,只有在絕對需要時才使用ReleaseComObject。如果要調用此方法以確保在確定的時間釋放COM組件,請考慮使用FinalReleaseComObject方法。

最後,你必須明白,無論你在你身邊做什麼,都不能保證COM對象會做任何確定性的處理。這取決於COM對象,而不是.NET中的運行時可調用包裝器。你所做的只是說「沒有更多的這個COM對象的引用」。那麼,很顯然,這與當本地超出範圍時發生的情況幾乎是一樣的,最終會收集垃圾。

+0

感謝您的詳細信息。我正在使用Microsoft.Office.Interop。Excel和已閱讀關於在後臺運行的excel進程以及在我看到他們已經使用Marshal.ReleaseComObject的示例中的很多問題。你會建議使用FinalReleaseComObject嗎? – mHelpMe

+1

@mHelpMe不,絕對不是。只要關閉它 - 在Excel COM對象上有'Close'或類似的東西來做到這一點。這將立即釋放Excel進程,與ReleaseComObject不同,它更友好。 – Luaan