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?
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...