Search code examples
c#unmanagedidisposable

IDisposable pattern, is SafeFileHandle an unmanaged resource?


Take the following snippet of IDisposable pattern generated by Resharper:

[NotNull]
private SafeFileHandle Handle { get; }

#region IDisposable

private bool IsDisposed { get; set; }

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

private void ReleaseUnmanagedResources()
{
    // TODO release unmanaged resources here
}

private void Dispose(bool disposing)
{
    if (IsDisposed)
        return;

    ReleaseUnmanagedResources();

    if (disposing)
        Handle.Dispose();

    IsDisposed = true;
}

~Whatever()
{
    Dispose(false);
}

Resharper considers SafeFileHandle as a managed resource, but this handle is about an unmanaged resource (CreateFile).

Question:

Should a SafeFileHandle be considered a managed or unmanaged resource when disposing it?


Solution

  • All C# classes and structs are managed resources1.

    Unmanaged resources are typically pointed to by an IntPtr, or something similar. You normally need to do something very deliberate to get your hands on one (such as P/Invoking some native method, or using one of the methods on Marshal).

    SafeFileHandle is a subclass of SafeHandle, which is a type specifically made to wrap unmanaged resources. SafeHandle defines its own finalizer, which releases the unmanaged resource in a suitable way if necessary.


    It's good advice to never own your own unmanaged resources, and instead always use a SafeHandle / CriticalFinalizerObject subclass to manage them.

    This avoids one of the big P/Invoke pitfalls, and also means you don't have to implement the full IDisposable pattern in your code: you only need to define a Dispose() method which calls Dispose() on your SafeHandles, and don't need to implement a finalizer.

    (Some people may need to deviate from this for performance reasons, but those people are few and far between)


    1Generic types with an unmanaged constraint aside...