Disposable types with unmanaged resources should declare finalizer

Rule ND1302 Design

Reports disposable types (System.IDisposable / IAsyncDisposable) with no finalizer (Object.Finalize()) that contain fields suggesting unmanaged resources:

- System.IntPtr

- System.UIntPtr

- System.Runtime.InteropServices.HandleRef

Disabled by default: it typically reports false positives for classes merely referencing managed resources without the responsibility to dispose them. Uncomment warnif count > 0 to enable.

How to fix

Implement a finalizer that calls your Dispose() method.

CQLinq source

This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.

// <Name>Disposable types with unmanaged resources should declare finalizer</Name>
// <Id>ND1302:DisposableTypesWithUnmanagedResourcesShouldDeclareFinalizer</Id>

// This default rule is disabled by default,
// see in the rule description (below) why.
// warnif count > 0

// Several IDisposable type can be found if several .NET Fx are referenced.
let iDisposables = ThirdParty.Types.WithFullNameIn("System.IDisposable", "System.IAsyncDisposable")
where iDisposables.Any() // in case the code base doesn't use at all System.IDisposable or IAsyncDisposable

let disposableTypes = Application.Types.ThatImplementAny(iDisposables)
let unmanagedResourcesFields = disposableTypes.ChildFields().Where(f => 
   !f.IsStatic && 
    f.FieldType != null && 
    f.FieldType.FullNameEqualsAny(
       "System.IntPtr",
       "System.UIntPtr",
       "System.Runtime.InteropServices.HandleRef")).ToHashSetEx()
let disposableTypesWithUnmanagedResource = unmanagedResourcesFields.ParentTypes()

from t in disposableTypesWithUnmanagedResource
where !t.HasFinalizer
let unmanagedResourcesTypeFields = unmanagedResourcesFields.Intersect(t.InstanceFields)
select new { 
   t, 
   unmanagedResourcesTypeFields,
   //Debt = 10.ToMinutes().ToDebt(),
   //Severity = Severity.Critical
}

//<Expl>
// The *{0}* hold unmanaged resources through *{1}* but doesn't have a finalizer.
//</Expl>


//<Desc>
// Reports disposable types (*System.IDisposable* / *IAsyncDisposable*) with
// no finalizer (*Object.Finalize()*) that contain fields suggesting
// unmanaged resources:
//
// - *System.IntPtr*
//
// - *System.UIntPtr*
//
// - *System.Runtime.InteropServices.HandleRef*
//
// Disabled by default: it typically reports *false positives* for classes
// merely referencing managed resources without the responsibility to dispose
// them. Uncomment *warnif count > 0* to enable.
//</Desc>

//<HowToFix>
// Implement a finalizer that calls your *Dispose()* method.
//</HowToFix>

Design: all 16 items