Disposable types with unmanaged resources should declare finalizer
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.
- 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>
Open in the interactive Rules Explorer · All default rules
Design: all 16 items
- Avoid custom delegates ND1300
- Types with disposable instance fields must be disposable ND1301
- Disposable types with unmanaged resources should declare finalizer ND1302
- Methods that create disposable object(s) and that don't call Dispose() ND1303
- Disposable Types Must Unsubscribe Events ND1315
- Classes that are candidate to be turned into structures ND1304
- Avoid namespaces with few types ND1305
- Nested types should not be visible ND1306
- Declare types in namespaces ND1307
- Empty static constructor can be discarded ND1308
- Instances size shouldn't be too big ND1309
- Attribute classes should be sealed ND1310
- Don't use obsolete types, methods or fields ND1311
- Do implement methods that throw NotImplementedException ND1312
- Override equals and operator equals on value types ND1313
- Boxing/unboxing should be avoided ND1314