Skip to content

Appendix B: Disposables

Rx represents subscriptions using the existing IDisposable interface. This design choice means we can use existing language features that know how to work with this interface. Rx also provides several public implementations of IDisposable. These can be found in the System.Reactive.Disposables namespace. This appendix briefly describes each of them.

With the exception of ScheduledDisposable, these have no particular connection to Rx, and can be useful in any code that needs to work with IDisposable. (This code all lives in System.Reactive though, so although you could uses these features entirely outside of Rx-based code, you will still be taking a dependency on Rx.NET if you do so.)


This static property exposes an implementation of IDisposable that performs no action when the Dispose method is invoked. This can be useful when you are obliged to supply an IDisposable (which can happen if you use Observable.Create) but don't need to do anything upon disposal.


This static method exposes an implementation of IDisposable that invokes the method supplied when the Dispose method is invoked. As the implementation follows the guidance to be idempotent, the action will only be called on the first time the Dispose method is invoked.


This class implements IDisposable.Dispose method and also defines a read-only property IsDisposed. IsDisposed is false when the class is constructed, and is set to true when the Dispose method is invoked.


The CancellationDisposable class offers an integration point between the .NET cancellation paradigm (CancellationTokenSource) and the resource management paradigm (IDisposable). You can create an instance of the CancellationDisposable class by providing a CancellationTokenSource to the constructor, or by having the parameterless constructor create one for you. Calling Dispose will invoke the Cancel method on the CancellationTokenSource. There are two properties (Token and IsDisposed) that CancellationDisposable exposes; they are wrappers for the CancellationTokenSource properties, respectively Token and IsCancellationRequested.


The CompositeDisposable type allows you to treat many disposable resources as one. You can create an instance of CompositeDisposable by passing in a params array of disposable resources. Calling Dispose on the CompositeDisposable will call dispose on each of these resources in the order they were provided. Additionally, the CompositeDisposable class implements ICollection<IDisposable>; this allows you to add and remove resources from the collection. After the CompositeDisposable has been disposed of, any further resources that are added to this collection will be disposed of instantly. Any item that is removed from the collection is also disposed of, regardless of whether the collection itself has been disposed of. This includes usage of both the Remove and Clear methods.


ContextDisposable allows you to enforce that disposal of a resource is performed on a given SynchronizationContext. The constructor requires both a SynchronizationContext and an IDisposable resource. When the Dispose method is invoked on the ContextDisposable, the provided resource will be disposed of on the specified context.


The MultipleAssignmentDisposable exposes a read-only IsDisposed property and a read/write property Disposable. Invoking the Dispose method on the MultipleAssignmentDisposable will dispose of the current value held by the Disposable property. It will then set that value to null. As long as the MultipleAssignmentDisposable has not been disposed of, you are able to set the Disposable property to IDisposable values as you would expect. Once the MultipleAssignmentDisposable has been disposed, attempting to set the Disposable property will cause the value to be instantly disposed of; meanwhile, Disposable will remain null.


The RefCountDisposable offers the ability to prevent the disposal of an underlying resource until all dependent resources have been disposed. You need an underlying IDisposable value to construct a RefCountDisposable. You can then call the GetDisposable method on the RefCountDisposable instance to retrieve a dependent resource. Each time a call to GetDisposable is made, an internal counter is incremented. Each time one of the dependent disposables from GetDisposable is disposed, the counter is decremented. Only if the counter reaches zero will the underlying be disposed of. This allows you to call Dispose on the RefCountDisposable itself before or after the count is zero.


In a similar fashion to ContextDisposable, the ScheduledDisposable type allows you to specify a scheduler, onto which the underlying resource will be disposed. You need to pass both the instance of IScheduler and instance of IDisposable to the constructor. When the ScheduledDisposable instance is disposed of, the disposal of the underlying resource will be executed through the provided scheduler.


SerialDisposable is very similar to MultipleAssignmentDisposable, as they both expose a read/write Disposable property. The contrast between them is that whenever the Disposable property is set on a SerialDisposable, the previous value is disposed of. Like the MultipleAssignmentDisposable, once the SerialDisposable has been disposed of, the Disposable property will be set to null and any further attempts to set it will have the value disposed of. The value will remain as null.


The SingleAssignmentDisposable class also exposes IsDisposed and Disposable properties. Like MultipleAssignmentDisposable and SerialDisposable, the Disposable value will be set to null when the SingleAssignmentDisposable is disposed of. The difference in implementation here is that the SingleAssignmentDisposable will throw an InvalidOperationException if there is an attempt to set the Disposable property while the value is not null and the SingleAssignmentDisposable has not been disposed of.

Ian Griffiths

Technical Fellow I

Ian Griffiths

Ian has worked in various aspects of computing, including computer networking, embedded real-time systems, broadcast television systems, medical imaging, and all forms of cloud computing. Ian is a Technical Fellow at endjin, and Microsoft MVP in Developer Technologies. He is the author of O'Reilly's Programming C# 10.0, and has written Pluralsight courses on WPF (and here) and the TPL. He's a maintainer of Reactive Extensions for .NET, Reaqtor, and endjin's 50+ open source projects. Technology brings him joy.