我不认为以前有人问过这个问题。我对在密封类上实现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)是不必要的。
另外,finalizer是否是严格必要的?欢迎所有的想法。
发布于 2009-09-13 22:06:24
终结器是必要的后备机制,用于在忘记调用Dispose时最终释放非托管资源。
不,您不应该在sealed类中声明virtual方法。它根本不会编译。此外,不建议在sealed类中声明新的protected成员。
发布于 2009-09-13 22:16:33
一个小的补充;在一般的情况下,一个常见的模式是有一个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;
}
}发布于 2009-09-13 22:29:50
来自Joe Duffy's Weblog
对于密封的类,不需要遵循此模式,这意味着您只需实现终结器并使用简单的方法(即C#中的~T() (
)和Dispose() )进行处置。在选择后一种方法时,您的代码仍然应该遵循下面关于终结化和处置逻辑实现的指导原则。
所以,是的,你应该做得很好。
正如Mehrdad提到的,您确实需要终结器。如果你想避免它,你可以看看SafeHandle。我没有足够的P/Invoke经验来建议正确的用法。
https://stackoverflow.com/questions/1418970
复制相似问题