NCode.Disposables 5.2.1

Prefix Reserved
dotnet add package NCode.Disposables --version 5.2.1                
NuGet\Install-Package NCode.Disposables -Version 5.2.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NCode.Disposables" Version="5.2.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add NCode.Disposables --version 5.2.1                
#r "nuget: NCode.Disposables, 5.2.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install NCode.Disposables as a Cake Addin
#addin nuget:?package=NCode.Disposables&version=5.2.1

// Install NCode.Disposables as a Cake Tool
#tool nuget:?package=NCode.Disposables&version=5.2.1                

ci Nuget

NCode.Disposables

This library provides a set of useful IDisposable and IAsyncDisposable implementations. For brevity, the IDisposable interface is used in the examples below, but the same implementations are available for IAsyncDisposable as well.

DisposeAsync If Available

Provides an extension method that will call the DisposeAsync method if it is available on the IDisposable resource. If the DisposeAsync method is not available, then the Dispose method is called instead.

async ValueTask Example()
{
    IDisposable resource = CreateSomeResource();
    await resource.DisposeAsyncIfAvailable();
}

Disposable Async Adapter

Provides an IAsyncDisposable adapter that wraps an IDisposable resource and forwards the DisposeAsync method to the Dispose method of the underlying resource.

async ValueTask Example()
{
    IDisposable resource = CreateSomeResource();
    IAsyncDisposable asyncDisposable = AsyncDisposable.Adapt(resource);
    await asyncDisposable.DisposeAsync();
}

Disposable Empty

Provides an implementation of IDisposable that is empty and performs nothing (i.e. nop) when Dispose is called.

void Example()
{
    // using singleton instance:
    IDisposable disposable1 = Disposable.Empty;
    disposable1.Dispose();
    
    // using new instance:
    IDisposable disposable2 = new DisposableEmpty();
    disposable2.Dispose();
}

Disposable Action

Provides an IDisposable implementation that will invoke an Action delegate when Dispose is called. If the Dispose method is called multiple times, the underlying action is invoked only once on the first call.

void Example()
{
    IDisposable disposable = Disposable.Create(() =>
        Console.WriteLine("I am disposed."));
    // ...
    disposable.Dispose();
}

Disposable Aggregate

Provides an IDisposable implementation that contains (i.e. aggregates) a property to another underlying IDisposable resource. The underlying resource may be assigned or retrieved multiple times as long as the aggregate hasn't been disposed yet.

void Example()
{
    IDisposable resource = CreateSomeResource();
    // ...
    var aggregate = Disposable.Aggregate(resource);
    // ...
    if (SomeCondition) {
        var previous = aggregate.Disposable;
        // ...
        aggregate.Disposable = CreateSomeOtherResource();
    }
    aggregate.Dispose();
    // ...
}

Disposable Collection

Provides an IDisposable collection that contains other IDisposable resources that will be disposed when the collection itself is disposed. The items in the collection are disposed in reverse order that they are added. The items in the collection may be added, removed, or cleared at any time before the collection is disposed itself.

void Example()
{
    IDisposable resource1 = CreateResource1();
    IDisposable resource2 = CreateResource2();
    // ...
    var collection = Disposable.Collection(resource1, resource2);
    // ...
    var resource3 = CreateResource3();
    if (!collection.Contains(resource3))
        collection.Add(resource3);
    // ...
    collection.Dispose();
}

Disposable Reference Count

Provides an IDisposable implementation that uses reference counting and only disposes the underlying resource when all the leases have been disposed (i.e. reference count is zero). The leases are not idempotent safe and consumers must take care to not dispose the same lease multiple times otherwise the underlying resource will be disposed prematurely. One solution for consumers is to assign the lease to default after disposing it.

void Example()
{
    IDisposable resource = CreateResource();
    // ...
    var firstLease = SharedReference.Create(resource);
    var secondLease = first.AddReference();
    var thirdLease = second.AddReference();
    // ...
    firstLease.Value.DoSomething();
    firstLease.Dispose();
    firstLease = default;
    // ...
    secondLease.Value.DoSomethingElse();
    secondLease.Dispose();
    secondLease = default;
    // ...
    thirdLease.Value.DoSomethingElse();
    thirdLease.Dispose();
    thirdLease = default;
    // the resource will be disposed here after
    // all 3 leases have been disposed...
}

Disposable Context

Provides an IDisposable implementation that will invoke the Dispose method of an underlying resource using an asynchronous or synchronous operation from a SynchronizationContext. If the Dispose method is called multiple times, the underlying resource is only disposed once on the first call.

void Example()
{
    IDisposable resource = CreateResource();
    // ...
    const bool async = true;
    var context = SynchronizationContext.Current;
    var disposable = Disposable.Context(resource, context, async);
    // ...
    disposable.Dispose()
}

Feedback

Please provide any feedback, comments, or issues to this GitHub project here.

Release Notes

  • v1.0.0 - Initial release
  • v1.0.1 - Unknown changes
  • v2.0.1 - Unknown changes
  • 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 idempotent option to certain methods.
  • v4.4.0 - Refactored the idempotent option 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
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
5.2.1 82 11/29/2024
5.1.1 94 11/27/2024
5.1.0 128 5/16/2024
5.0.2 121 5/16/2024
5.0.1 129 5/16/2024
5.0.0 124 5/16/2024
4.4.0 108 5/15/2024
4.3.0 128 5/15/2024
4.2.0 120 4/29/2024
4.1.0 111 4/28/2024
4.0.0 109 4/21/2024
3.1.0 112 4/21/2024
3.0.1 120 4/21/2024
3.0.0 118 4/21/2024
2.0.2 1,249 1/22/2017
2.0.1 957 1/22/2017
1.0.1 1,299 2/11/2016
1.0.0 1,209 1/30/2016

Built on 2024-11-29 23:33:36Z