Methods that create disposable object(s) and that don't call Dispose()

Rule ND1303 Design

Enumerates methods creating disposable object(s) without calling any Dispose() method. Not a rule: this is acceptable when the objects are disposed elsewhere. Easily refactored to target specific disposable types or caller methods, and turned into a rule.

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>Methods that create disposable object(s) and that don't call Dispose()</Name>
// <Id>ND1303:MethodsThatCreateDisposableObjectAndThatDontCallDispose</Id>

// Just uncomment this to transform this code query into a code rule.
// warnif count > 0

// Several IDisposable types can be found if several .NET Fx are referenced.
let iDisposables = ThirdParty.Types.WithFullName("System.IDisposable")
where iDisposables.Any() // in case the code base doesn't use at all System.IDisposable
 
// Build sequences of disposableTypes and disposeMethods
let disposableTypes = Types.ThatImplementAny(iDisposables).Concat(iDisposables)
let disposeMethods = disposableTypes.ChildMethods().WithName("Dispose()").ToHashSetEx()


// -> You can refine this code query by assigning to disposableTypesToLookAfter something like:
//    disposableTypes.WithFullNameIn("Namespace.TypeName1", "Namespace.TypeName2", ...)
let disposableTypesToLookAfter = disposableTypes


// -> You can refine this code query by assigning to methodsToLookAfter something like:
//    Application.Assemblies.WithNameLike("Asm").ChildMethods()
let methodsToLookAfter = Application.Methods


// Enumerate methods that create any disposable type, without calling Dispose()
from m in methodsToLookAfter.ThatCreateAny(disposableTypesToLookAfter )

where !m.MethodsCalled.Intersect(disposeMethods).Any()
select new {
   m,
   disposableObjectsCreated = disposableTypes.Where(t => m.CreateA(t)),
   m.MethodsCalled,
   //Debt = 10.ToMinutes().ToDebt(),
   //Severity = Severity.Low
}

//<Expl>
// The *{0}* instantiates disposable types without calling any *Dispose()* method.
// Disposable type{1?:s} instantiated: *{1}*
//</Expl>

//<Desc>
// Enumerates methods creating disposable object(s) without calling any
// Dispose() method. Not a rule: this is acceptable when the objects are
// disposed elsewhere. Easily refactored to target specific disposable types
// or caller methods, and turned into a rule.
//</Desc>

Design: all 16 items