diff --git a/Rx.NET/Source/src/System.Reactive/Disposables/AnonymousDisposable.cs b/Rx.NET/Source/src/System.Reactive/Disposables/AnonymousDisposable.cs
index 83347dac96..ff009a55d6 100644
--- a/Rx.NET/Source/src/System.Reactive/Disposables/AnonymousDisposable.cs
+++ b/Rx.NET/Source/src/System.Reactive/Disposables/AnonymousDisposable.cs
@@ -37,4 +37,40 @@ public void Dispose()
Interlocked.Exchange(ref _dispose, null)?.Invoke();
}
}
+
+ ///
+ /// Represents a Action-based disposable that can hold onto some state.
+ ///
+ internal sealed class AnonymousDisposable : ICancelable
+ {
+ private TState _state;
+ private volatile Action _dispose;
+
+ ///
+ /// Constructs a new disposable with the given action used for disposal.
+ ///
+ /// The state to be passed to the disposal action.
+ /// Disposal action which will be run upon calling Dispose.
+ public AnonymousDisposable(TState state, Action dispose)
+ {
+ System.Diagnostics.Debug.Assert(dispose != null);
+
+ _state = state;
+ _dispose = dispose;
+ }
+
+ ///
+ /// Gets a value that indicates whether the object is disposed.
+ ///
+ public bool IsDisposed => _dispose == null;
+
+ ///
+ /// Calls the disposal action if and only if the current instance hasn't been disposed yet.
+ ///
+ public void Dispose()
+ {
+ Interlocked.Exchange(ref _dispose, null)?.Invoke(_state);
+ _state = default;
+ }
+ }
}
diff --git a/Rx.NET/Source/src/System.Reactive/Disposables/Disposable.cs b/Rx.NET/Source/src/System.Reactive/Disposables/Disposable.cs
index ae75070f59..1de3e3cbfa 100644
--- a/Rx.NET/Source/src/System.Reactive/Disposables/Disposable.cs
+++ b/Rx.NET/Source/src/System.Reactive/Disposables/Disposable.cs
@@ -60,6 +60,21 @@ public static IDisposable Create(Action dispose)
return new AnonymousDisposable(dispose);
}
+ ///
+ /// Creates a disposable object that invokes the specified action when disposed.
+ ///
+ /// The state to be passed to the action.
+ /// Action to run during the first call to . The action is guaranteed to be run at most once.
+ /// The disposable object that runs the given action upon disposal.
+ /// is null.
+ public static IDisposable Create(TState state, Action dispose)
+ {
+ if (dispose == null)
+ throw new ArgumentNullException(nameof(dispose));
+
+ return new AnonymousDisposable(state, dispose);
+ }
+
///
/// Gets the value stored in or a null if
/// was already disposed.
diff --git a/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.approved.txt b/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.approved.txt
index ac5e63583b..a4016d0d9f 100644
--- a/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.approved.txt
+++ b/Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.approved.txt
@@ -568,6 +568,7 @@ namespace System.Reactive.Disposables
{
public static System.IDisposable Empty { get; }
public static System.IDisposable Create(System.Action dispose) { }
+ public static System.IDisposable Create(TState state, System.Action dispose) { }
}
public interface ICancelable : System.IDisposable
{