我认为以前没有问过这个问题.我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();
}
}
Run Code Online (Sandbox Code Playgroud)
我假设因为MemBlock完全是密封的,并且永远不会从另一个实现a的类中派生出来virtual protected Dispose(bool disposing).
那么,终结者是否必须?欢迎所有的想法.
Meh*_*ari 14
如果你忘了打电话,终结器作为最终释放非托管资源的后备机制是必要的Dispose.
不,你不应该virtual在sealed类中声明一个方法.根本不会编译.此外,不建议protected在sealed类中声明新成员.
Mar*_*ell 10
一个小小的补充; 在一般情况下,一个常见的模式是有一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
来自Joe Duffy的博客:
对于密封类,不需要遵循这种模式,这意味着您应该使用简单的方法(即C#中的~T()(Finalize)和Dispose()来实现Finalizer和Dispose.选择后一种方法时,您的代码仍应遵循以下关于最终化和处置逻辑的实现的指导原则.
所以,是的,你应该很好.
你确实需要像Mehrdad所提到的终结器.如果你想避免它,你可以看一下SafeHandle.我没有足够的P/Invoke经验来建议正确的用法.
| 归档时间: |
|
| 查看次数: |
7531 次 |
| 最近记录: |