簡體   English   中英

在密封的類上實現IDisposable

[英]Implementing IDisposable on a sealed class

我認為以前沒有問過這個問題。 我對在密封類上實現IDisposable的最佳方法感到困惑 - 特別是一個不從基類繼承的密封類。 (也就是說,這是一個“純密封的類”,這是我的術語。)

也許你們有些人同意我的看法,實施IDisposable的指導方針非常混亂。 也就是說,我想知道我打算實現IDisposable是足夠和安全的。

我正在做一些通過Marshal.AllocHGlobal分配IntPtr P / Invoke代碼,當然,我想干凈地處理我創建的非托管內存。 所以我在考慮這樣的事情

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public sealed class MemBlock : IDisposable
{
     IntPtr ptr;
     int length;

     MemBlock(int size)
     {
           ptr = Marshal.AllocHGlobal(size);
           length = size;
     }

     public void Dispose()
     {
          if (ptr != IntPtr.Zero)
          {
               Marshal.FreeHGlobal(ptr);
               ptr = IntPtr.Zero;
               GC.SuppressFinalize(this);
          }
     }

     ~MemBlock()
     {
           Dispose();
     }    
}

我假設因為MemBlock是完全密封的,並且永遠不會從另一個類派生出來,因此不需要實現virtual protected Dispose(bool disposing)

那么,終結者是否必須? 歡迎所有的想法。

如果您忘記調用Dispose則終結器必須作為最終釋放非托管資源的回退機制。

不,您不應該在sealed類中聲明virtual方法。 根本不會編譯。 此外,不建議在sealed類中聲明新的protected成員。

一個小小的補充; 一般情況下,一個常見的模式是使用Dispose(bool disposing)方法,這樣你就可以知道你是否處於Dispose (有更多的東西可用)和終結器(你不應該真正接觸任何其他連接的托管)對象)。

例如:

 public void Dispose() { Dispose(true); }
 ~MemBlock() { Dispose(false); }
 void Dispose(bool disposing) { // would be protected virtual if not sealed 
     if(disposing) { // only run this logic when Dispose is called
         GC.SuppressFinalize(this);
         // and anything else that touches managed objects
     }
     if (ptr != IntPtr.Zero) {
          Marshal.FreeHGlobal(ptr);
          ptr = IntPtr.Zero;
     }
 }

來自Joe Duffy的博客

對於密封類,不需要遵循這種模式,這意味着您應該使用簡單的方法(即C#中的~T()(Finalize)和Dispose()來實現Finalizer和Dispose。 選擇后一種方法時,您的代碼仍應遵循以下關於最終化和處置邏輯的實現的指導原則。

所以,是的,你應該很好。

你確實需要像Mehrdad所提到的終結器。 如果你想避免它,你可以看一下SafeHandle 我沒有足夠的P / Invoke經驗來建議正確的用法。

您不能在密封類中聲明虛方法。 同樣在密封類中聲明受保護的成員會給出編譯器警告。 所以你已經正確實現了它。 從終結器中調用GC.SuppressFinalize(this)並不是出於明顯原因所必需的,但它不會造成傷害。

在處理非托管資源時,擁有終結器是必不可少的,因為它們不會自動釋放,您必須在終結器中執行它,並在對象被垃圾回收后自動調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM