[英]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.