When writing wrappers for unmanaged resources, you should subclass SafeHandle
rather than trying to implement IDisposable
and a finalizer yourself. Your SafeHandle
subclass should be as small and simple as possible to minimize the chance of a handle leak. This likely means that your SafeHandle implementation would an internal implementation detail of a class which wraps it to provide a usable API. This class ensures that, even if a program leaks your SafeHandle
instance, your unmanaged handle is released.
using System.Runtime.InteropServices;
class MyHandle : SafeHandle
{
public override bool IsInvalid => handle == IntPtr.Zero;
public MyHandle() : base(IntPtr.Zero, true)
{ }
public MyHandle(int length) : this()
{
SetHandle(Marshal.AllocHGlobal(length));
}
protected override bool ReleaseHandle()
{
Marshal.FreeHGlobal(handle);
return true;
}
}
Disclaimer: This example is an attempt to show how to guard a managed resource with SafeHandle
which implements IDisposable
for you and configures finalizers appropriately. It is very contrived and likely pointless to allocate a chunk of memory in this manner.