可在密封类上实现ID

问题描述 投票:22回答:4

我认为以前没有问过这个问题。我对在密封类上实现IDisposable的最佳方法有些困惑,具体来说,该密封类不继承自基类。 (也就是说,这是我的固定学期的“纯密封课程”。)

也许你们中的一些人同意我,因为实施IDisposable的准则非常令人困惑。就是说,我想知道我打算实现IDisposable的方式是充分且安全的。

我正在执行一些P / Invoke代码,它们从IntPtr分配Marshal.AllocHGlobal,自然,我想干净地处置我创建的非托管内存。所以我在想像这样的东西

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)

而且,终结器是否绝对必要?欢迎所有想法。

c# pinvoke
4个回答
13
投票

终结器是必需的,作为一种回退机制,如果您忘记调用Dispose,最终可以释放不受管理的资源。

否,您不应该在virtual类中声明sealed方法。它根本不会编译。另外,不建议在protected类中声明新的sealed成员。


9
投票

一个小的补充;在general情况下,常见的模式是使用Dispose(bool disposing)方法,这样您就可以知道自己是否在Dispose(有更多可用的东西)与finalizer(在这里您不应真正接触)任何其他连接的受管对象)。

例如:

 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;
     }
 }

8
投票

来自Joe Duffy's Weblog

对于密封类,此模式需要不遵循,意味着你应该只需实现您的终结器,用简单的方法处理(即〜T()(在C#中完成)和Dispose()。选择后一种路线时,代码仍应遵守以下有关准则实施定稿和处理逻辑。

所以是的,你应该很好。

您确实需要Mehrdad所述的终结器。如果要避免这种情况,可以查看SafeHandle。我没有足够的使用P / Invoke的经验来建议正确的用法。


1
投票

您不能在密封的类中声明虚拟方法。此外,在密封类中声明受保护的成员也会向您发出编译器警告。因此,您已经正确实现了它。出于显而易见的原因,不必在终结器中调用GC.SuppressFinalize(this),但这不会造成损害。

处理非托管资源时,必须具有终结器,因为它们不会自动释放,因此必须在终结器中进行处理,并在对象被垃圾回收后被自动调用。

© www.soinside.com 2019 - 2024. All rights reserved.