System.DisposableObject
10.1.0
dotnet add package System.DisposableObject --version 10.1.0
NuGet\Install-Package System.DisposableObject -Version 10.1.0
<PackageReference Include="System.DisposableObject" Version="10.1.0" />
<PackageVersion Include="System.DisposableObject" Version="10.1.0" />
<PackageReference Include="System.DisposableObject" />
paket add System.DisposableObject --version 10.1.0
#r "nuget: System.DisposableObject, 10.1.0"
#:package System.DisposableObject@10.1.0
#addin nuget:?package=System.DisposableObject&version=10.1.0
#tool nuget:?package=System.DisposableObject&version=10.1.0
System.DisposableObject
System.DisposableObject is a lightweight .NET base-class library that implements the Dispose Pattern so you don't have to. Inherit from one of two abstract base classes and override a pair of simple hook methods — the boilerplate is handled for you.
DisposableObject— implementsIDisposablewith a full finalizer, double-dispose guard, and re-entrancy guard.AsyncDisposableObject— extendsDisposableObjectwithIAsyncDisposable, enablingawait usingwhile keeping synchronous callers working.
Table of Contents
- Installation
- Quick Start
- API Reference
- Advanced Usage
- How Disposal Works
- Contributing
- License
- References
Installation
Install the package from NuGet:
dotnet add package System.DisposableObject
Or via the Package Manager Console in Visual Studio:
Install-Package System.DisposableObject
Quick Start
Synchronous disposal — DisposableObject
Inherit from DisposableObject and override whichever hook methods your class needs.
using System;
public class DatabaseConnection : DisposableObject
{
private SqlConnection _connection;
public DatabaseConnection(string connectionString)
{
_connection = new SqlConnection(connectionString);
_connection.Open();
}
protected override void OnDisposeManagedObjects()
{
// Dispose CLR-managed objects (objects that implement IDisposable).
_connection?.Dispose();
_connection = null;
}
protected override void OnDisposeUnmanagedObjects()
{
// Release native handles, file descriptors, COM objects, etc.
// Do NOT reference other .NET objects here — this method can be
// called by the GC finalizer after managed objects have been collected.
}
}
Use it with a using statement (recommended):
using (var db = new DatabaseConnection(connectionString))
{
// Work with db here.
} // OnDisposeManagedObjects() and OnDisposeUnmanagedObjects() are called here.
Or call Dispose() explicitly:
var db = new DatabaseConnection(connectionString);
// ... use db ...
db.Dispose();
Async disposal — AsyncDisposableObject
Inherit from AsyncDisposableObject when your class wraps async-capable resources or when callers may use await using.
using System;
using System.Threading.Tasks;
public class AsyncDatabaseConnection : AsyncDisposableObject
{
private SqlConnection _connection;
public AsyncDatabaseConnection(string connectionString)
{
_connection = new SqlConnection(connectionString);
}
protected override void OnDisposeManagedObjects()
{
// Synchronous cleanup of managed resources.
_connection?.Dispose();
_connection = null;
}
protected override void OnDisposeUnmanagedObjects()
{
// Native resource cleanup.
}
}
Use it with await using (recommended for async code):
await using (var db = new AsyncDatabaseConnection(connectionString))
{
// Work with db here.
} // DisposeAsync() → Dispose() → hooks called here.
Synchronous callers still work as before:
using (var db = new AsyncDatabaseConnection(connectionString))
{
// Works fine — AsyncDisposableObject inherits DisposableObject.
}
API Reference
DisposableObject
Namespace: System
Assembly: System.DisposableObject
Inherits: System.Dynamic.DynamicObject
Implements: IDisposable
DisposableObject is abstract. You cannot instantiate it directly; create a class that inherits from it.
Protected properties
| Property | Type | Description |
|---|---|---|
IsDisposed |
bool |
true after Dispose() has been called. Read-only to subclasses; set internally. |
InProcessOfDisposing |
bool (virtual) |
true while disposal is in progress. Used as a re-entrancy guard. |
AssertWhenNotDisposed |
bool (virtual) |
When true, a Trace.Assert or warning is emitted if the finalizer fires before Dispose(). Defaults to false. |
Public methods
| Method | Description |
|---|---|
void Dispose() |
Disposes the object. Calls OnDisposeManagedObjects() and OnDisposeUnmanagedObjects(), then calls GC.SuppressFinalize(this). Safe to call multiple times. |
bool TryInvokeMember(...) |
Overrides DynamicObject.TryInvokeMember. Calls AccessMethod() before delegating, ensuring that dynamic member invocations throw ObjectDisposedException on disposed instances. |
Protected virtual methods (hooks)
Override any of the following in your subclass:
| Method | When called | Notes |
|---|---|---|
OnDisposeManagedObjects() |
During an explicit Dispose() call only |
Safe to access other managed (.NET) objects here. |
OnDisposeUnmanagedObjects() |
During both explicit Dispose() and GC finalization |
Do not reference managed objects here — they may already have been collected. |
AccessMethod() |
Call at the start of any public method in your subclass | Throws ObjectDisposedException if IsDisposed is true. |
OnGetClassName() |
Called when a diagnostic message is generated | Override to return a meaningful class name (defaults to this.ToString()). |
OnNotDisposedProperly() |
Called from the finalizer when AssertWhenNotDisposed is true |
Return true to suppress the base-class warning/assertion and handle it yourself. |
AsyncDisposableObject
Namespace: System
Assembly: System.DisposableObject
Inherits: DisposableObject
Implements: IDisposable, IAsyncDisposable
Adds a DisposeAsync() method on top of everything provided by DisposableObject. The hook methods (OnDisposeManagedObjects, OnDisposeUnmanagedObjects) are identical — there is no separate async hook.
Public methods (in addition to DisposableObject)
| Method | Description |
|---|---|
ValueTask DisposeAsync() |
Calls the synchronous Dispose() and returns ValueTask.CompletedTask. Safe to call multiple times and to mix with synchronous Dispose() calls. |
Advanced Usage
Guarding methods against use after disposal
Call AccessMethod() at the start of any public or internal method in your subclass to ensure the object has not been disposed:
public class MyResource : DisposableObject
{
private byte[] _buffer = new byte[1024];
public int ReadData(byte[] destination, int count)
{
// Throws ObjectDisposedException if Dispose() was already called.
this.AccessMethod();
// ... perform the read ...
return count;
}
protected override void OnDisposeManagedObjects()
{
_buffer = null;
}
}
After Dispose() is called, any subsequent call to ReadData will throw ObjectDisposedException with the name of the type.
Debugging — detect objects not disposed properly
Enable AssertWhenNotDisposed in your subclass constructor during development to catch objects that are garbage-collected without an explicit Dispose():
public class LeakDetectingResource : DisposableObject
{
public LeakDetectingResource()
{
// Enable only in DEBUG builds to help catch disposal leaks.
#if DEBUG
this.AssertWhenNotDisposed = true;
#endif
}
protected override void OnDisposeManagedObjects() { /* ... */ }
}
When AssertWhenNotDisposed is true and the GC finalizer runs without a prior Dispose():
- If
OnNotDisposedProperly()returnsfalse(the default), aTrace.Assertfires. - If
OnNotDisposedProperly()returnstrue, aTrace.TraceWarningis emitted instead and no assertion fires.
Custom class name in diagnostic messages
Override OnGetClassName() to provide a more readable name in trace/assert messages:
public class MyService : DisposableObject
{
protected override string OnGetClassName() => nameof(MyService);
protected override void OnDisposeManagedObjects() { /* ... */ }
}
How Disposal Works
The diagram below shows the code paths during object lifetime.
Explicit call: obj.Dispose()
│
▼
DisposableObject.Dispose()
│ ── calls GC.SuppressFinalize(this)
▼
DisposableObject.Dispose(disposing: true)
├─► OnDisposeManagedObjects() ← override in subclass
└─► OnDisposeUnmanagedObjects() ← override in subclass
GC finalizer: ~DisposableObject()
│ (only reached if Dispose() was never called)
▼
DisposableObject.Dispose(disposing: false)
└─► OnDisposeUnmanagedObjects() ← managed objects must NOT be touched
Async call: await obj.DisposeAsync()
│
▼
AsyncDisposableObject.DisposeAsync()
│ ── delegates to synchronous Dispose()
└─► (same flow as explicit synchronous call above)
Key guarantees provided by the base classes:
| Guarantee | How it is enforced |
|---|---|
| Hooks called at most once | IsDisposed flag checked before calling hooks |
| No recursive disposal | InProcessOfDisposing re-entrancy guard |
| Finalizer suppressed after explicit dispose | GC.SuppressFinalize(this) called from Dispose() |
| Dynamic member access blocked after dispose | TryInvokeMember calls AccessMethod() |
Contributing
Contributions are welcome. Please open an issue or submit a pull request on GitHub.
License
This library is distributed under the GNU Lesser General Public License v3.0 or later (LGPL-3.0-or-later). See LICENSE for the full text.
References
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (12)
Showing the top 5 NuGet packages that depend on System.DisposableObject:
| Package | Downloads |
|---|---|
|
Diamond.Core.System.TemporaryFolder
This library provides code performance tools. |
|
|
Diamond.Core.Repository.EntityFrameworkCore
This library provides an implementation of the repository that can be used with Entity Framework Core. |
|
|
System.Data.FileDatabase
A library for easy access to File based databases such as Microsoft Access, flat files or Excel Spreadsheets. |
|
|
Diamond.Patterns.Context
This library provides context implementations the work-flows and other context based operations. |
|
|
Diamond.Patterns.System
This library provides some basic support functionality. |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on System.DisposableObject:
| Repository | Stars |
|---|---|
|
porrey/Virtual-ZPL-Printer
An ethernet based virtual Zebra Label Printer that can be used to test applications that produce bar code labels.
|