NCode.Disposables
5.3.0
Prefix Reserved
dotnet add package NCode.Disposables --version 5.3.0
NuGet\Install-Package NCode.Disposables -Version 5.3.0
<PackageReference Include="NCode.Disposables" Version="5.3.0" />
<PackageVersion Include="NCode.Disposables" Version="5.3.0" />
<PackageReference Include="NCode.Disposables" />
paket add NCode.Disposables --version 5.3.0
#r "nuget: NCode.Disposables, 5.3.0"
#:package NCode.Disposables@5.3.0
#addin nuget:?package=NCode.Disposables&version=5.3.0
#tool nuget:?package=NCode.Disposables&version=5.3.0
NCode.Disposables
A comprehensive .NET library providing useful IDisposable and IAsyncDisposable implementations for common resource management patterns.
Features
Core Implementations
- Empty Disposable - No-op singleton for null object pattern
- Action Disposable - Execute a delegate on dispose (idempotent)
- Aggregate Disposable - Wrapper with replaceable underlying resource
- Collection Disposable - Manage multiple disposables with LIFO disposal order
- Context Disposable - Dispose on a specific
SynchronizationContext(e.g., UI thread) - Shared Reference - Reference-counted resource sharing with lease pattern
Async Support
All implementations have async counterparts (IAsyncDisposable):
AsyncDisposable.Empty,Create(),Aggregate(),Collection(),Shared()AsyncDisposableAdapter- WrapsIDisposableasIAsyncDisposable
Extension Methods
DisposeAsyncIfAvailable()- CallsDisposeAsyncif available, otherwiseDisposeDisposeAll()/DisposeAllAsync()- Dispose all items in a collection (LIFO order)AsSharedReference()- Convert a disposable to a shared reference with leasing
Quick Reference
| Feature | Sync API | Async API |
|---|---|---|
| Empty (no-op) | Disposable.Empty |
AsyncDisposable.Empty |
| Action callback | Disposable.Create(action) |
AsyncDisposable.Create(func) |
| Aggregate wrapper | Disposable.Aggregate(disposable) |
AsyncDisposable.Aggregate(disposable) |
| Collection | Disposable.Collection(items) |
AsyncDisposable.Collection(items) |
| Shared reference | SharedReference.Create(value) |
AsyncSharedReference.Create(value) |
| Context disposal | Disposable.Context(disposable, ctx) |
— |
| Adapt sync→async | — | AsyncDisposable.Adapt(disposable) |
Usage Examples
Empty Disposable
// Singleton instance - useful as default/placeholder
IDisposable disposable = Disposable.Empty;
disposable.Dispose(); // no-op
Action Disposable
// Execute cleanup logic on dispose (idempotent - runs only once)
IDisposable disposable = Disposable.Create(() => Console.WriteLine("Disposed!"));
disposable.Dispose(); // prints "Disposed!"
disposable.Dispose(); // no-op
Aggregate Disposable
// Wrapper allowing the underlying resource to be swapped
var aggregate = Disposable.Aggregate(initialResource);
aggregate.Disposable = newResource; // swap resource
aggregate.Dispose(); // disposes current resource
Collection Disposable
// Manage multiple disposables - disposed in reverse (LIFO) order
var collection = Disposable.Collection(resource1, resource2, resource3);
collection.Add(resource4);
collection.Remove(resource2); // removed items are NOT disposed
collection.Dispose(); // disposes: resource4, resource3, resource1
Shared Reference (Reference Counting)
// Share a resource with reference counting
IDisposable resource = CreateExpensiveResource();
var lease1 = SharedReference.Create(resource);
var lease2 = lease1.AddReference();
var lease3 = lease2.AddReference();
lease1.Value.DoWork();
lease1.Dispose();
lease2.Value.DoWork();
lease2.Dispose();
lease3.Value.DoWork();
lease3.Dispose(); // resource disposed here (ref count = 0)
Context Disposable
// Dispose on a specific SynchronizationContext (e.g., UI thread)
var context = SynchronizationContext.Current;
var disposable = Disposable.Context(uiResource, context, async: false);
disposable.Dispose(); // runs on the context's thread
Async Adapter
// Wrap IDisposable as IAsyncDisposable
IDisposable syncResource = CreateResource();
IAsyncDisposable asyncResource = AsyncDisposable.Adapt(syncResource);
await asyncResource.DisposeAsync();
Extension Methods
// Dispose async if available, otherwise sync
await disposable.DisposeAsyncIfAvailable();
// Dispose all items in a collection (LIFO order)
var items = new object[] { resource1, resource2, nonDisposable, resource3 };
items.DisposeAll(); // disposes only IDisposable items, in reverse order
// Convert to shared reference
using var lease = myDisposable.AsSharedReference();
Feedback
Please provide any feedback, comments, or issues to this GitHub project here.
Release Notes
- v1.0.0 - Initial release
- v2.0.2 - Port to .NET Core/Standard
- v3.0.0 - Port to .NET 8.0 and refactor shared reference implementation
- v3.0.1 - Updated xml documentation
- v3.1.0 - Split ISharedReference into ISharedReferenceScope and ISharedReferenceProvider
- v4.0.0 - Revert the split
- v4.1.0 - Added async support
- v4.2.0 - Added async adapter
- v4.3.0 - Added DisposeAsyncIfAvailable extension. Added
idempotentoption to certain methods. - v4.4.0 - Refactored the
idempotentoption to use function overloads. - v5.0.0 - Refactored shared references/leases to use structs
- v5.0.1 - Removing dead code
- v5.0.2 - Removing more dead code
- v5.1.0 - Allow creating of async shared references without requiring async callsite
- v5.1.1 - Minor resharper cleanup
- v5.2.1 - Collections can be any object instead of just IDisposable or IAsyncDisposable
- v5.3.0 - .NET 10 upgrade
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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.
-
net8.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on NCode.Disposables:
| Package | Downloads |
|---|---|
|
NCode.Collections.Providers
Default implementations for dynamic, change-aware collection providers. Includes static, observable, composite, and periodic polling data sources with automatic change notifications via IChangeToken. Provides dependency injection integration with Microsoft.Extensions.DependencyInjection. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.3.0 | 120 | 1/17/2026 |
| 5.2.1 | 202 | 11/29/2024 |
| 5.1.1 | 176 | 11/27/2024 |
| 5.1.0 | 191 | 5/16/2024 |
| 5.0.2 | 199 | 5/16/2024 |
| 5.0.1 | 206 | 5/16/2024 |
| 5.0.0 | 185 | 5/16/2024 |
| 4.4.0 | 187 | 5/15/2024 |
| 4.3.0 | 179 | 5/15/2024 |
| 4.2.0 | 185 | 4/29/2024 |
| 4.1.0 | 182 | 4/28/2024 |
| 4.0.0 | 178 | 4/21/2024 |
| 3.1.0 | 182 | 4/21/2024 |
| 3.0.1 | 178 | 4/21/2024 |
| 3.0.0 | 195 | 4/21/2024 |
| 2.0.2 | 1,700 | 1/22/2017 |
| 2.0.1 | 1,305 | 1/22/2017 |
| 1.0.1 | 1,688 | 2/11/2016 |
| 1.0.0 | 1,582 | 1/30/2016 |
Built on 2026-01-17 15:40:31Z