简体   繁体   English

在密封的类上实现IDisposable

[英]Implementing IDisposable on a sealed class

I don't think this question has been asked before. 我认为以前没有问过这个问题。 I'm a bit confused on the best way to implement IDisposable on a sealed class—specifically, a sealed class that does not inherit from a base class. 我对在密封类上实现IDisposable的最佳方法感到困惑 - 特别是一个不从基类继承的密封类。 (That is, a "pure sealed class" which is my made up term.) (也就是说,这是一个“纯密封的类”,这是我的术语。)

Perhaps some of you agree with me in that the guidelines for implementing IDisposable are very confusing. 也许你们有些人同意我的看法,实施IDisposable的指导方针非常混乱。 That said, I want to know that the way I intend to implement IDisposable is sufficient and safe. 也就是说,我想知道我打算实现IDisposable是足够和安全的。

I'm doing some P/Invoke code that allocates an IntPtr through Marshal.AllocHGlobal and naturally, I want to cleanly dispose of the unmanaged memory I've created. 我正在做一些通过Marshal.AllocHGlobal分配IntPtr P / Invoke代码,当然,我想干净地处理我创建的非托管内存。 So I'm thinking of something like this 所以我在考虑这样的事情

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

I'm assuming that because MemBlock is completely sealed and never derives from another class that implementing a virtual protected Dispose(bool disposing) is not necessary. 我假设因为MemBlock是完全密封的,并且永远不会从另一个类派生出来,因此不需要实现virtual protected Dispose(bool disposing)

Also, is the finalizer strictly necessary? 那么,终结者是否必须? All thoughts welcome. 欢迎所有的想法。

The finalizer is necessary as a fallback mechanism to eventually free unmanaged resources if you forgot to call Dispose . 如果您忘记调用Dispose则终结器必须作为最终释放非托管资源的回退机制。

No, you shouldn't declare a virtual method in a sealed class. 不,您不应该在sealed类中声明virtual方法。 It wouldn't compile at all. 根本不会编译。 Also, it's not recommended to declare new protected members in sealed classes. 此外,不建议在sealed类中声明新的protected成员。

A minor addition; 一个小小的补充; in the general case, a common pattern is to have a Dispose(bool disposing) method, so that you know whether you are in Dispose (where more things are available) vs the finalizer (where you shouldn't really touch any other connected managed objects). 一般情况下,一个常见的模式是使用Dispose(bool disposing)方法,这样你就可以知道你是否处于Dispose (有更多的东西可用)和终结器(你不应该真正接触任何其他连接的托管)对象)。

For example: 例如:

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

From Joe Duffy's Weblog : 来自Joe Duffy的博客

For sealed classes, this pattern need not be followed, meaning you should simply implement your Finalizer and Dispose with the simple methods (ie ~T() (Finalize) and Dispose() in C#). 对于密封类,不需要遵循这种模式,这意味着您应该使用简单的方法(即C#中的~T()(Finalize)和Dispose()来实现Finalizer和Dispose。 When choosing the latter route, your code should still adhere to the guidelines below regarding implementation of finalization and dispose logic. 选择后一种方法时,您的代码仍应遵循以下关于最终化和处置逻辑的实现的指导原则。

So yes, you should be good. 所以,是的,你应该很好。

You do need the finalizer as Mehrdad mentioned. 你确实需要像Mehrdad所提到的终结器。 If you want to avoid it, you might take a look at SafeHandle . 如果你想避免它,你可以看一下SafeHandle I don't have enough experience with P/Invoke to suggest the correct usage. 我没有足够的P / Invoke经验来建议正确的用法。

You cannot declare virtual methods in a sealed class. 您不能在密封类中声明虚方法。 Also declaring protected members in a sealed class gives you a compiler warning. 同样在密封类中声明受保护的成员会给出编译器警告。 So you've implemented it correctly. 所以你已经正确实现了它。 Calling GC.SuppressFinalize(this) from within the finalizer is not necessary for obvious reasons but it cannot harm. 从终结器中调用GC.SuppressFinalize(this)并不是出于明显原因所必需的,但它不会造成伤害。

Having a finalizer is essential when dealing with unmanaged resources, because they are not freed automatically, you have to do it in the finalizer with is called automatically after the object has been garbage collected. 在处理非托管资源时,拥有终结器是必不可少的,因为它们不会自动释放,您必须在终结器中执行它,并在对象被垃圾回收后自动调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 正确处置实现IDisposable的类 - Proper disposing of class implementing IDisposable 在自定义类中为实体框架实现 IDisposable - Implementing IDisposable for Entity Framework in custom class 将IDisposable(一次性模式)实现为服务(类成员) - Implementing IDisposable (the Disposable Pattern) as a service (class member) 在公开Begin / End方法的类中实现IDisposable - Implementing IDisposable in a class exposing Begin/End methods 实现 IDisposable 的 class 可以成为托管资源吗? - Can a class implementing IDisposable be a managed resource? 密封实现类时覆盖单个接口方法 - Overriding a single interface method when the implementing class is sealed 在可使用泛型类型的泛型类型的类上实现IDisposable - Implementing IDisposable on Class with Generic Type Where Generic Type Is Disposable 正确实现Finalize和Dispose的方法(当父类实现IDisposable时) - Correct way of implementing Finalize and Dispose(When parent class implements IDisposable) 确定IDisposable应该扩展接口还是在实现该接口的类上实现 - Determining if IDisposable should extend an interface or be implemented on a class implementing said interface 从Idisposable实现泛型类时编译时的不同行为? - Different behaviour at compile time while implementing generic class from Idisposable?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM