Browse Source

Merge pull request #1406 from danielcweber/DisposableUtils

Replace most uses of Disposable.Utils
Daniel Weber 5 years ago
parent
commit
d8dbf12254
52 changed files with 402 additions and 297 deletions
  1. 4 4
      Rx.NET/Source/src/System.Reactive/Concurrency/CatchScheduler.cs
  2. 4 4
      Rx.NET/Source/src/System.Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs
  3. 3 3
      Rx.NET/Source/src/System.Reactive/Concurrency/DefaultScheduler.cs
  4. 3 3
      Rx.NET/Source/src/System.Reactive/Concurrency/EventLoopScheduler.cs
  5. 4 4
      Rx.NET/Source/src/System.Reactive/Concurrency/LocalScheduler.TimerQueue.cs
  6. 5 5
      Rx.NET/Source/src/System.Reactive/Concurrency/ScheduledItem.cs
  7. 3 3
      Rx.NET/Source/src/System.Reactive/Concurrency/Scheduler.Async.cs
  8. 3 3
      Rx.NET/Source/src/System.Reactive/Concurrency/Scheduler.Services.Emulation.cs
  9. 4 4
      Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs
  10. 12 12
      Rx.NET/Source/src/System.Reactive/Concurrency/TaskPoolScheduler.cs
  11. 7 7
      Rx.NET/Source/src/System.Reactive/Concurrency/UserWorkItem.cs
  12. 0 33
      Rx.NET/Source/src/System.Reactive/Disposables/Disposable.Utils.cs
  13. 5 5
      Rx.NET/Source/src/System.Reactive/Disposables/MultipleAssignmentDisposable.cs
  14. 43 0
      Rx.NET/Source/src/System.Reactive/Disposables/MultipleAssignmentDisposableValue.cs
  15. 5 5
      Rx.NET/Source/src/System.Reactive/Disposables/ScheduledDisposable.cs
  16. 5 5
      Rx.NET/Source/src/System.Reactive/Disposables/SerialDisposable.cs
  17. 43 0
      Rx.NET/Source/src/System.Reactive/Disposables/SerialDisposableValue.cs
  18. 5 5
      Rx.NET/Source/src/System.Reactive/Disposables/SingleAssignmentDisposable.cs
  19. 52 0
      Rx.NET/Source/src/System.Reactive/Disposables/SingleAssignmentDisposableValue.cs
  20. 7 7
      Rx.NET/Source/src/System.Reactive/Disposables/StableCompositeDisposable.cs
  21. 3 3
      Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs
  22. 3 3
      Rx.NET/Source/src/System.Reactive/Internal/SafeObserver.cs
  23. 11 11
      Rx.NET/Source/src/System.Reactive/Internal/ScheduledObserver.cs
  24. 4 4
      Rx.NET/Source/src/System.Reactive/Internal/Sink.cs
  25. 5 5
      Rx.NET/Source/src/System.Reactive/Internal/SystemClock.Default.cs
  26. 3 3
      Rx.NET/Source/src/System.Reactive/Joins/JoinObserver.cs
  27. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/AppendPrepend.cs
  28. 15 15
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs
  29. 8 8
      Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs
  30. 4 4
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ConcatMany.cs
  31. 4 4
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs
  32. 8 8
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Generate.cs
  33. 5 5
      Rx.NET/Source/src/System.Reactive/Linq/Observable/GetEnumerator.cs
  34. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Multicast.cs
  35. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/PushToPullAdapter.cs
  36. 4 4
      Rx.NET/Source/src/System.Reactive/Linq/Observable/RefCount.cs
  37. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/RepeatWhen.cs
  38. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/RetryWhen.cs
  39. 12 12
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Sample.cs
  40. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SequenceEqual.cs
  41. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Skip.cs
  42. 9 9
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipUntil.cs
  43. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs
  44. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Take.cs
  45. 2 2
      Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLast.cs
  46. 8 8
      Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeUntil.cs
  47. 12 12
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Throttle.cs
  48. 12 12
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Timeout.cs
  49. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Using.cs
  50. 4 4
      Rx.NET/Source/src/System.Reactive/Linq/Observable/WithLatestFrom.cs
  51. 16 16
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.cs
  52. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Creation.cs

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Concurrency/CatchScheduler.cs

@@ -97,7 +97,7 @@ namespace System.Reactive.Concurrency
         {
             private sealed class PeriodicallyScheduledWorkItem<TState> : IDisposable
             {
-                private IDisposable _cancel;
+                private SingleAssignmentDisposableValue _cancel;
                 private bool _failed;
 
                 private readonly Func<TState, TState> _action;
@@ -109,12 +109,12 @@ namespace System.Reactive.Concurrency
                     _action = action;
 
                     // Note that avoiding closure allocation here would introduce infinite generic recursion over the TState argument
-                    Disposable.SetSingle(ref _cancel, scheduler._scheduler.SchedulePeriodic(state, period, state1 => Tick(state1).state));
+                    _cancel.Disposable = scheduler._scheduler.SchedulePeriodic(state, period, state1 => Tick(state1).state);
                 }
 
                 public void Dispose()
                 {
-                    Disposable.Dispose(ref _cancel);
+                    _cancel.Dispose();
                 }
 
                 private (PeriodicallyScheduledWorkItem<TState> @this, TState state) Tick(TState state)
@@ -144,7 +144,7 @@ namespace System.Reactive.Concurrency
                             throw;
                         }
 
-                        Disposable.Dispose(ref _cancel);
+                        _cancel.Dispose();
                         return default;
                     }
                 }

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs

@@ -154,7 +154,7 @@ namespace System.Reactive.Concurrency
         {
             private volatile object? _state;
             private Action<object?> _action;
-            private IDisposable _timer;
+            private SingleAssignmentDisposableValue _timer;
 
             private static readonly object DisposedState = new object();
 
@@ -163,7 +163,7 @@ namespace System.Reactive.Concurrency
                 _state = state;
                 _action = action;
 
-                Disposable.SetSingle(ref _timer, new System.Threading.Timer(static @this => ((Timer)@this!).Tick(), this, dueTime, TimeSpan.FromMilliseconds(Timeout.Infinite)));
+                _timer.Disposable = new System.Threading.Timer(static @this => ((Timer)@this!).Tick(), this, dueTime, TimeSpan.FromMilliseconds(Timeout.Infinite));
             }
 
             private void Tick()
@@ -178,13 +178,13 @@ namespace System.Reactive.Concurrency
                 }
                 finally
                 {
-                    Disposable.Dispose(ref _timer);
+                    _timer.Dispose();
                 }
             }
 
             public void Dispose()
             {
-                Disposable.Dispose(ref _timer);
+                _timer.Dispose();
 
                 _action = Stubs<object?>.Ignore;
                 _state = DisposedState;

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Concurrency/DefaultScheduler.cs

@@ -161,7 +161,7 @@ namespace System.Reactive.Concurrency
                 private readonly TState _state;
                 private readonly Action<TState, ICancelable> _action;
 
-                private IDisposable? _cancel;
+                private SingleAssignmentDisposableValue _cancel;
 
                 public LongScheduledWorkItem(TState state, Action<TState, ICancelable> action)
                 {
@@ -186,10 +186,10 @@ namespace System.Reactive.Concurrency
 
                 public void Dispose()
                 {
-                    Disposable.Dispose(ref _cancel);
+                    _cancel.Dispose();
                 }
 
-                public bool IsDisposed => Disposable.GetIsDisposed(ref _cancel);
+                public bool IsDisposed => _cancel.IsDisposed;
             }
 
             public static readonly ISchedulerLongRunning Instance = new LongRunning();

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Concurrency/EventLoopScheduler.cs

@@ -66,7 +66,7 @@ namespace System.Reactive.Concurrency
         /// <summary>
         /// Disposable that always holds the timer to dispatch the first element in the queue.
         /// </summary>
-        private IDisposable? _nextTimer;
+        private SerialDisposableValue _nextTimer;
 
         /// <summary>
         /// Flag indicating whether the event loop should quit. When set, the event should be signaled as well to
@@ -265,7 +265,7 @@ namespace System.Reactive.Concurrency
                 if (!_disposed)
                 {
                     _disposed = true;
-                    Disposable.Dispose(ref _nextTimer);
+                    _nextTimer.Dispose();
                     _evt.Release();
                 }
             }
@@ -334,7 +334,7 @@ namespace System.Reactive.Concurrency
                             _nextItem = next;
 
                             var due = next.DueTime - _stopwatch.Elapsed;
-                            Disposable.TrySetSerial(ref _nextTimer, ConcurrencyAbstractionLayer.Current.StartTimer(Tick, next, due));
+                            _nextTimer.Disposable = ConcurrencyAbstractionLayer.Current.StartTimer(Tick, next, due);
                         }
                     }
 

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Concurrency/LocalScheduler.TimerQueue.cs

@@ -422,7 +422,7 @@ namespace System.Reactive.Concurrency
             public readonly LocalScheduler Scheduler;
             public readonly DateTimeOffset DueTime;
 
-            private IDisposable? _disposable;
+            private SingleAssignmentDisposableValue _disposable;
             private int _hasRun;
 
             protected WorkItem(LocalScheduler scheduler, DateTimeOffset dueTime)
@@ -445,9 +445,9 @@ namespace System.Reactive.Concurrency
                 {
                     try
                     {
-                        if (!Disposable.GetIsDisposed(ref _disposable))
+                        if (!_disposable.IsDisposed)
                         {
-                            Disposable.SetSingle(ref _disposable, InvokeCore(scheduler));
+                            _disposable.Disposable = InvokeCore(scheduler);
                         }
                     }
                     finally
@@ -461,7 +461,7 @@ namespace System.Reactive.Concurrency
 
             public int CompareTo(WorkItem? other) => DueTime.CompareTo(other!.DueTime);
 
-            public void Dispose() => Disposable.Dispose(ref _disposable);
+            public void Dispose() => _disposable.Dispose();
         }
 
         /// <summary>

+ 5 - 5
Rx.NET/Source/src/System.Reactive/Concurrency/ScheduledItem.cs

@@ -14,7 +14,7 @@ namespace System.Reactive.Concurrency
     public abstract class ScheduledItem<TAbsolute> : IScheduledItem<TAbsolute>, IComparable<ScheduledItem<TAbsolute>>, IDisposable
         where TAbsolute : IComparable<TAbsolute>
     {
-        private IDisposable? _disposable;
+        private SingleAssignmentDisposableValue _disposable;
         private readonly IComparer<TAbsolute> _comparer;
 
         /// <summary>
@@ -39,9 +39,9 @@ namespace System.Reactive.Concurrency
         /// </summary>
         public void Invoke()
         {
-            if (!Disposable.GetIsDisposed(ref _disposable))
+            if (!_disposable.IsDisposed)
             {
-                Disposable.SetSingle(ref _disposable, InvokeCore());
+                _disposable.Disposable = InvokeCore();
             }
         }
 
@@ -146,12 +146,12 @@ namespace System.Reactive.Concurrency
         /// <summary>
         /// Cancels the work item by disposing the resource returned by <see cref="InvokeCore"/> as soon as possible.
         /// </summary>
-        public void Cancel() => Disposable.Dispose(ref _disposable);
+        public void Cancel() => _disposable.Dispose();
 
         /// <summary>
         /// Gets whether the work item has received a cancellation request.
         /// </summary>
-        public bool IsCanceled => Disposable.GetIsDisposed(ref _disposable);
+        public bool IsCanceled => _disposable.IsDisposed;
 
         void IDisposable.Dispose() => Cancel();
     }

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Concurrency/Scheduler.Async.cs

@@ -13,7 +13,7 @@ namespace System.Reactive.Concurrency
         private sealed class AsyncInvocation<TState> : IDisposable
         {
             private readonly CancellationTokenSource _cts = new CancellationTokenSource();
-            private IDisposable? _run;
+            private SingleAssignmentDisposableValue _run;
 
             public IDisposable Run(IScheduler self, TState s, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action)
             {
@@ -27,7 +27,7 @@ namespace System.Reactive.Concurrency
 
                         t.Exception?.Handle(static e => e is OperationCanceledException);
 
-                        Disposable.SetSingle(ref @this._run, t.Result);
+                        @this._run.Disposable = t.Result;
                     },
                     this,
                     TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.NotOnCanceled);
@@ -38,7 +38,7 @@ namespace System.Reactive.Concurrency
             public void Dispose()
             {
                 _cts.Cancel();
-                Disposable.Dispose(ref _run);
+                _run.Dispose();
             }
         }
 

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Concurrency/Scheduler.Services.Emulation.cs

@@ -367,7 +367,7 @@ namespace System.Reactive.Concurrency
             private const int Suspended = 2;
             private const int Disposed = 3;
 
-            private IDisposable? _task;
+            private SingleAssignmentDisposableValue _task;
 
             public IDisposable Start()
             {
@@ -377,13 +377,13 @@ namespace System.Reactive.Concurrency
                 _nextDue = _period;
                 _runState = Running;
 
-                Disposable.TrySetSingle(ref _task, _scheduler.Schedule(this, _nextDue, static (@this, a) => @this.Tick(a)));
+                _task.Disposable = _scheduler.Schedule(this, _nextDue, static (@this, a) => @this.Tick(a));
                 return this;
             }
 
             void IDisposable.Dispose()
             {
-                Disposable.Dispose(ref _task);
+                _task.Dispose();
                 Cancel();
             }
 

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs

@@ -117,7 +117,7 @@ namespace System.Reactive.Concurrency
                 private readonly IObservable<TSource> _source;
                 private readonly IObserver<TSource> _observer;
                 private readonly SynchronizationContext _context;
-                private IDisposable? _cancel;
+                private SingleAssignmentDisposableValue _cancel;
 
                 public Subscription(IObservable<TSource> source, SynchronizationContext context, IObserver<TSource> observer)
                 {
@@ -128,9 +128,9 @@ namespace System.Reactive.Concurrency
                     context.PostWithStartComplete(
                         @this =>
                         {
-                            if (!Disposable.GetIsDisposed(ref @this._cancel))
+                            if (!@this._cancel.IsDisposed)
                             {
-                                Disposable.SetSingle(ref @this._cancel, new ContextDisposable(@this._context, @this._source.SubscribeSafe(@this._observer)));
+                                @this._cancel.Disposable = new ContextDisposable(@this._context, @this._source.SubscribeSafe(@this._observer));
                             }
                         },
                         this);
@@ -138,7 +138,7 @@ namespace System.Reactive.Concurrency
 
                 public void Dispose()
                 {
-                    Disposable.Dispose(ref _cancel);
+                    _cancel.Dispose();
                 }
             }
 

+ 12 - 12
Rx.NET/Source/src/System.Reactive/Concurrency/TaskPoolScheduler.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Concurrency
             private readonly TaskPoolScheduler _scheduler;
             private readonly Func<IScheduler, TState, IDisposable> _action;
 
-            private IDisposable _cancel;
+            private SerialDisposableValue _cancel;
 
             public ScheduledWorkItem(TaskPoolScheduler scheduler, TState state, Func<IScheduler, TState, IDisposable> action)
             {
@@ -30,7 +30,7 @@ namespace System.Reactive.Concurrency
 
                 var cancelable = new CancellationDisposable();
 
-                Disposable.SetSingle(ref _cancel, cancelable);
+                _cancel.Disposable = cancelable;
 
                 scheduler._taskFactory.StartNew(
                     thisObject =>
@@ -60,7 +60,7 @@ namespace System.Reactive.Concurrency
                         // exceptions at stage 2. If the exception isn't handled at the Rx level, it
                         // propagates by means of a rethrow, falling back to behavior in 3.
                         //
-                        Disposable.TrySetSerial(ref @this._cancel, @this._action(@this._scheduler, @this._state));
+                        @this._cancel.Disposable = @this._action(@this._scheduler, @this._state);
                     },
                     this,
                     cancelable.Token);
@@ -68,7 +68,7 @@ namespace System.Reactive.Concurrency
 
             public void Dispose()
             {
-                Disposable.Dispose(ref _cancel);
+                _cancel.Dispose();
             }
         }
 
@@ -78,7 +78,7 @@ namespace System.Reactive.Concurrency
             private readonly TaskPoolScheduler _scheduler;
             private readonly Func<IScheduler, TState, IDisposable> _action;
 
-            private IDisposable _cancel;
+            private MultipleAssignmentDisposableValue _cancel;
 
             public SlowlyScheduledWorkItem(TaskPoolScheduler scheduler, TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
             {
@@ -87,16 +87,16 @@ namespace System.Reactive.Concurrency
                 _scheduler = scheduler;
 
                 var ct = new CancellationDisposable();
-                Disposable.SetSingle(ref _cancel, ct);
+                _cancel.Disposable = ct;
 
                 TaskHelpers.Delay(dueTime, ct.Token).ContinueWith(
                     (_, thisObject) =>
                     {
                         var @this = (SlowlyScheduledWorkItem<TState>)thisObject!;
 
-                        if (!Disposable.GetIsDisposed(ref @this._cancel))
+                        if (!@this._cancel.IsDisposed)
                         {
-                            Disposable.TrySetMultiple(ref @this._cancel, @this._action(@this._scheduler, @this._state));
+                            @this._cancel.Disposable = @this._action(@this._scheduler, @this._state);
                         }
                     },
                     this,
@@ -107,7 +107,7 @@ namespace System.Reactive.Concurrency
 
             public void Dispose()
             {
-                Disposable.Dispose(ref _cancel);
+                _cancel.Dispose();
             }
         }
 
@@ -116,7 +116,7 @@ namespace System.Reactive.Concurrency
             private readonly TState _state;
             private readonly Action<TState, ICancelable> _action;
 
-            private IDisposable? _cancel;
+            private SingleAssignmentDisposableValue _cancel;
 
             public LongScheduledWorkItem(TaskPoolScheduler scheduler, TState state, Action<TState, ICancelable> action)
             {
@@ -141,10 +141,10 @@ namespace System.Reactive.Concurrency
 
             public void Dispose()
             {
-                Disposable.Dispose(ref _cancel);
+                _cancel.Dispose();
             }
 
-            public bool IsDisposed => Disposable.GetIsDisposed(ref _cancel);
+            public bool IsDisposed => _cancel.IsDisposed;
         }
 
         private static readonly Lazy<TaskPoolScheduler> LazyInstance = new Lazy<TaskPoolScheduler>(static () => new TaskPoolScheduler(new TaskFactory(TaskScheduler.Default)));

+ 7 - 7
Rx.NET/Source/src/System.Reactive/Concurrency/UserWorkItem.cs

@@ -8,8 +8,8 @@ namespace System.Reactive.Concurrency
 {
     internal sealed class UserWorkItem<TState> : IDisposable
     {
-        private IDisposable? _cancelRunDisposable;
-        private IDisposable? _cancelQueueDisposable;
+        private SingleAssignmentDisposableValue _cancelRunDisposable;
+        private SingleAssignmentDisposableValue _cancelQueueDisposable;
 
         private readonly TState _state;
         private readonly IScheduler _scheduler;
@@ -24,21 +24,21 @@ namespace System.Reactive.Concurrency
 
         public void Run()
         {
-            if (!Disposable.GetIsDisposed(ref _cancelRunDisposable))
+            if (!_cancelRunDisposable.IsDisposed)
             {
-                Disposable.SetSingle(ref _cancelRunDisposable, _action(_scheduler, _state));
+                _cancelRunDisposable.Disposable = _action(_scheduler, _state);
             }
         }
 
         public IDisposable CancelQueueDisposable
         {
-            set => Disposable.SetSingle(ref _cancelQueueDisposable, value);
+            set => _cancelQueueDisposable.Disposable = value;
         }
 
         public void Dispose()
         {
-            Disposable.Dispose(ref _cancelQueueDisposable);
-            Disposable.Dispose(ref _cancelRunDisposable);
+            _cancelQueueDisposable.Dispose();
+            _cancelRunDisposable.Dispose();
         }
     }
 }

+ 0 - 33
Rx.NET/Source/src/System.Reactive/Disposables/Disposable.Utils.cs

@@ -43,26 +43,6 @@ namespace System.Reactive.Disposables
                 : current;
         }
 
-        /// <summary>
-        /// Assigns <paramref name="value" /> to <paramref name="fieldRef" />.
-        /// </summary>
-        /// <returns>true if <paramref name="fieldRef" /> was assigned to <paramref name="value" /> and has not
-        /// been assigned before.</returns>
-        /// <returns>false if <paramref name="fieldRef" /> has been already disposed.</returns>
-        /// <exception cref="InvalidOperationException"><paramref name="fieldRef" /> has already been assigned a value.</exception>
-        internal static bool SetSingle([NotNullIfNotNull("value")] ref IDisposable? fieldRef, IDisposable? value)
-        {
-            var result = TrySetSingle(ref fieldRef, value);
-
-            if (result == TrySetSingleResult.AlreadyAssigned)
-            {
-                throw new InvalidOperationException(Strings_Core.DISPOSABLE_ALREADY_ASSIGNED);
-            }
-
-            return result == TrySetSingleResult.Success;
-        }
-
-        /// <summary>
         /// Tries to assign <paramref name="value" /> to <paramref name="fieldRef" />.
         /// </summary>
         /// <returns>A <see cref="TrySetSingleResult"/> value indicating the outcome of the operation.</returns>
@@ -145,19 +125,6 @@ namespace System.Reactive.Disposables
             }
         }
 
-        /// <summary>
-        /// Gets a value indicating whether <paramref name="fieldRef" /> has been disposed.
-        /// </summary>
-        /// <returns>true if <paramref name="fieldRef" /> has been disposed.</returns>
-        /// <returns>false if <paramref name="fieldRef" /> has not been disposed.</returns>
-        internal static bool GetIsDisposed([NotNullIfNotNull("fieldRef")] /*in*/ ref IDisposable? fieldRef)
-        {
-            // We use a sentinel value to indicate we've been disposed. This sentinel never leaks
-            // to the outside world (see the Disposable property getter), so no-one can ever assign
-            // this value to us manually.
-            return Volatile.Read(ref fieldRef) == BooleanDisposable.True;
-        }
-
         /// <summary>
         /// Disposes <paramref name="fieldRef" />. 
         /// </summary>

+ 5 - 5
Rx.NET/Source/src/System.Reactive/Disposables/MultipleAssignmentDisposable.cs

@@ -9,7 +9,7 @@ namespace System.Reactive.Disposables
     /// </summary>
     public sealed class MultipleAssignmentDisposable : ICancelable
     {
-        private IDisposable? _current;
+        private MultipleAssignmentDisposableValue _current;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="MultipleAssignmentDisposable"/> class with no current underlying disposable.
@@ -21,7 +21,7 @@ namespace System.Reactive.Disposables
         /// <summary>
         /// Gets a value that indicates whether the object is disposed.
         /// </summary>
-        public bool IsDisposed => Disposables.Disposable.GetIsDisposed(ref _current);
+        public bool IsDisposed => _current.IsDisposed;
 
         /// <summary>
         /// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
@@ -29,8 +29,8 @@ namespace System.Reactive.Disposables
         /// <remarks>If the <see cref="MultipleAssignmentDisposable"/> has already been disposed, assignment to this property causes immediate disposal of the given disposable object.</remarks>
         public IDisposable? Disposable
         {
-            get => Disposables.Disposable.GetValueOrDefault(ref _current);
-            set => Disposables.Disposable.TrySetMultiple(ref _current, value);
+            get => _current.Disposable;
+            set => _current.Disposable = value;
         }
 
         /// <summary>
@@ -38,7 +38,7 @@ namespace System.Reactive.Disposables
         /// </summary>
         public void Dispose()
         {
-            Disposables.Disposable.Dispose(ref _current);
+            _current.Dispose();
         }
     }
 }

+ 43 - 0
Rx.NET/Source/src/System.Reactive/Disposables/MultipleAssignmentDisposableValue.cs

@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT License.
+// See the LICENSE file in the project root for more information. 
+
+using System.Threading;
+
+namespace System.Reactive.Disposables
+{
+    /// <summary>
+    /// Represents a disposable resource whose underlying disposable resource can be swapped for another disposable resource.
+    /// </summary>
+    internal struct MultipleAssignmentDisposableValue : ICancelable
+    {
+        private IDisposable? _current;
+
+        /// <summary>
+        /// Gets a value that indicates whether the object is disposed.
+        /// </summary>
+        public bool IsDisposed =>
+            // We use a sentinel value to indicate we've been disposed. This sentinel never leaks
+            // to the outside world (see the Disposable property getter), so no-one can ever assign
+            // this value to us manually.
+            Volatile.Read(ref _current) == BooleanDisposable.True;
+
+        /// <summary>
+        /// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
+        /// </summary>
+        /// <remarks>If the <see cref="MultipleAssignmentDisposable"/> has already been disposed, assignment to this property causes immediate disposal of the given disposable object.</remarks>
+        public IDisposable? Disposable
+        {
+            get => Disposables.Disposable.GetValueOrDefault(ref _current);
+            set => Disposables.Disposable.TrySetMultiple(ref _current, value);
+        }
+
+        /// <summary>
+        /// Disposes the underlying disposable as well as all future replacements.
+        /// </summary>
+        public void Dispose()
+        {
+            Disposables.Disposable.Dispose(ref _current);
+        }
+    }
+}

+ 5 - 5
Rx.NET/Source/src/System.Reactive/Disposables/ScheduledDisposable.cs

@@ -11,7 +11,7 @@ namespace System.Reactive.Disposables
     /// </summary>
     public sealed class ScheduledDisposable : ICancelable
     {
-        private IDisposable _disposable;
+        private SingleAssignmentDisposableValue _disposable;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ScheduledDisposable"/> class that uses an <see cref="IScheduler"/> on which to dispose the disposable.
@@ -27,7 +27,7 @@ namespace System.Reactive.Disposables
             }
 
             Scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
-            Disposables.Disposable.SetSingle(ref _disposable, disposable);
+            _disposable.Disposable = disposable;
         }
 
         /// <summary>
@@ -38,16 +38,16 @@ namespace System.Reactive.Disposables
         /// <summary>
         /// Gets the underlying disposable. After disposal, the result is undefined.
         /// </summary>
-        public IDisposable Disposable => Disposables.Disposable.GetValueOrDefault(ref _disposable);
+        public IDisposable Disposable => _disposable.Disposable ?? Disposables.Disposable.Empty;
 
         /// <summary>
         /// Gets a value that indicates whether the object is disposed.
         /// </summary>
-        public bool IsDisposed => Disposables.Disposable.GetIsDisposed(ref _disposable);
+        public bool IsDisposed => _disposable.IsDisposed;
 
         /// <summary>
         /// Disposes the wrapped disposable on the provided scheduler.
         /// </summary>
-        public void Dispose() => Scheduler.ScheduleAction(this, scheduler => Disposables.Disposable.Dispose(ref scheduler._disposable));
+        public void Dispose() => Scheduler.ScheduleAction(this, scheduler => scheduler._disposable.Dispose());
     }
 }

+ 5 - 5
Rx.NET/Source/src/System.Reactive/Disposables/SerialDisposable.cs

@@ -9,7 +9,7 @@ namespace System.Reactive.Disposables
     /// </summary>
     public sealed class SerialDisposable : ICancelable
     {
-        private IDisposable? _current;
+        private SerialDisposableValue _current;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.SerialDisposable"/> class.
@@ -21,7 +21,7 @@ namespace System.Reactive.Disposables
         /// <summary>
         /// Gets a value that indicates whether the object is disposed.
         /// </summary>
-        public bool IsDisposed => Disposables.Disposable.GetIsDisposed(ref _current);
+        public bool IsDisposed => _current.IsDisposed;
 
         /// <summary>
         /// Gets or sets the underlying disposable.
@@ -29,8 +29,8 @@ namespace System.Reactive.Disposables
         /// <remarks>If the SerialDisposable has already been disposed, assignment to this property causes immediate disposal of the given disposable object. Assigning this property disposes the previous disposable object.</remarks>
         public IDisposable? Disposable
         {
-            get => Disposables.Disposable.GetValue(ref _current);
-            set => Disposables.Disposable.TrySetSerial(ref _current, value);
+            get => _current.Disposable;
+            set => _current.Disposable = value;
         }
 
         /// <summary>
@@ -38,7 +38,7 @@ namespace System.Reactive.Disposables
         /// </summary>
         public void Dispose()
         {
-            Disposables.Disposable.Dispose(ref _current);
+            _current.Dispose();
         }
     }
 }

+ 43 - 0
Rx.NET/Source/src/System.Reactive/Disposables/SerialDisposableValue.cs

@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT License.
+// See the LICENSE file in the project root for more information. 
+
+using System.Threading;
+
+namespace System.Reactive.Disposables
+{
+    /// <summary>
+    /// Represents a disposable resource whose underlying disposable resource can be replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource.
+    /// </summary>
+    internal struct SerialDisposableValue : ICancelable
+    {
+        private IDisposable? _current;
+
+        /// <summary>
+        /// Gets a value that indicates whether the object is disposed.
+        /// </summary>
+        public bool IsDisposed =>
+            // We use a sentinel value to indicate we've been disposed. This sentinel never leaks
+            // to the outside world (see the Disposable property getter), so no-one can ever assign
+            // this value to us manually.
+            Volatile.Read(ref _current) == BooleanDisposable.True;
+
+        /// <summary>
+        /// Gets or sets the underlying disposable.
+        /// </summary>
+        /// <remarks>If the SerialDisposable has already been disposed, assignment to this property causes immediate disposal of the given disposable object. Assigning this property disposes the previous disposable object.</remarks>
+        public IDisposable? Disposable
+        {
+            get => Disposables.Disposable.GetValue(ref _current);
+            set => Disposables.Disposable.TrySetSerial(ref _current, value);
+        }
+
+        /// <summary>
+        /// Disposes the underlying disposable as well as all future replacements.
+        /// </summary>
+        public void Dispose()
+        {
+            Disposables.Disposable.Dispose(ref _current);
+        }
+    }
+}

+ 5 - 5
Rx.NET/Source/src/System.Reactive/Disposables/SingleAssignmentDisposable.cs

@@ -10,7 +10,7 @@ namespace System.Reactive.Disposables
     /// </summary>
     public sealed class SingleAssignmentDisposable : ICancelable
     {
-        private IDisposable? _current;
+        private SingleAssignmentDisposableValue _current;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="SingleAssignmentDisposable"/> class.
@@ -22,7 +22,7 @@ namespace System.Reactive.Disposables
         /// <summary>
         /// Gets a value that indicates whether the object is disposed.
         /// </summary>
-        public bool IsDisposed => Disposables.Disposable.GetIsDisposed(ref _current);
+        public bool IsDisposed => _current.IsDisposed;
 
         /// <summary>
         /// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
@@ -30,8 +30,8 @@ namespace System.Reactive.Disposables
         /// <exception cref="InvalidOperationException">Thrown if the <see cref="SingleAssignmentDisposable"/> has already been assigned to.</exception>
         public IDisposable? Disposable
         {
-            get => Disposables.Disposable.GetValueOrDefault(ref _current);
-            set => Disposables.Disposable.SetSingle(ref _current, value);
+            get => _current.Disposable;
+            set => _current.Disposable = value;
         }
 
         /// <summary>
@@ -39,7 +39,7 @@ namespace System.Reactive.Disposables
         /// </summary>
         public void Dispose()
         {
-            Disposables.Disposable.Dispose(ref _current);
+            _current.Dispose();
         }
     }
 }

+ 52 - 0
Rx.NET/Source/src/System.Reactive/Disposables/SingleAssignmentDisposableValue.cs

@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT License.
+// See the LICENSE file in the project root for more information. 
+
+using System.Threading;
+
+namespace System.Reactive.Disposables
+{
+    /// <summary>
+    /// Represents a disposable resource which only allows a single assignment of its underlying disposable resource.
+    /// If an underlying disposable resource has already been set, future attempts to set the underlying disposable resource will throw an <see cref="InvalidOperationException"/>.
+    /// </summary>
+    internal struct SingleAssignmentDisposableValue
+    {
+        private IDisposable? _current;
+
+        /// <summary>
+        /// Gets a value that indicates whether the object is disposed.
+        /// </summary>
+        public bool IsDisposed =>
+            // We use a sentinel value to indicate we've been disposed. This sentinel never leaks
+            // to the outside world (see the Disposable property getter), so no-one can ever assign
+            // this value to us manually.
+            Volatile.Read(ref _current) == BooleanDisposable.True;
+
+        /// <summary>
+        /// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">Thrown if the <see cref="SingleAssignmentDisposable"/> has already been assigned to.</exception>
+        public IDisposable? Disposable
+        {
+            get => Disposables.Disposable.GetValueOrDefault(ref _current);
+            set
+            {
+                var result = Disposables.Disposable.TrySetSingle(ref _current, value);
+
+                if (result == TrySetSingleResult.AlreadyAssigned)
+                {
+                    throw new InvalidOperationException(Strings_Core.DISPOSABLE_ALREADY_ASSIGNED);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Disposes the underlying disposable.
+        /// </summary>
+        public void Dispose()
+        {
+            Disposables.Disposable.Dispose(ref _current);
+        }
+    }
+}

+ 7 - 7
Rx.NET/Source/src/System.Reactive/Disposables/StableCompositeDisposable.cs

@@ -90,21 +90,21 @@ namespace System.Reactive.Disposables
 
         private sealed class Binary : StableCompositeDisposable
         {
-            private IDisposable? _disposable1;
-            private IDisposable? _disposable2;
+            private SingleAssignmentDisposableValue _disposable1;
+            private SingleAssignmentDisposableValue _disposable2;
 
             public Binary(IDisposable disposable1, IDisposable disposable2)
             {
-                Volatile.Write(ref _disposable1, disposable1);
-                Volatile.Write(ref _disposable2, disposable2);
+                _disposable1.Disposable = disposable1;
+                _disposable2.Disposable = disposable2;
             }
 
-            public override bool IsDisposed => Disposable.GetIsDisposed(ref _disposable1);
+            public override bool IsDisposed => _disposable1.IsDisposed;
 
             public override void Dispose()
             {
-                Disposable.Dispose(ref _disposable1);
-                Disposable.Dispose(ref _disposable2);
+                _disposable1.Dispose();
+                _disposable2.Dispose();
             }
         }
 

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs

@@ -10,7 +10,7 @@ namespace System.Reactive
     {
         private readonly IObserver<T> _observer;
 
-        private IDisposable? _disposable;
+        private SingleAssignmentDisposableValue _disposable;
 
         public AutoDetachObserver(IObserver<T> observer)
         {
@@ -19,7 +19,7 @@ namespace System.Reactive
 
         public void SetResource(IDisposable resource)
         {
-            Disposable.SetSingle(ref _disposable, resource);
+            _disposable.Disposable = resource;
         }
 
         protected override void OnNextCore(T value)
@@ -100,7 +100,7 @@ namespace System.Reactive
 
             if (disposing)
             {
-                Disposable.Dispose(ref _disposable);
+                _disposable.Dispose();
             }
         }
     }

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Internal/SafeObserver.cs

@@ -66,7 +66,7 @@ namespace System.Reactive
             return new WrappingSafeObserver(observer);
         }
 
-        private IDisposable? _disposable;
+        private SingleAssignmentDisposableValue _disposable;
 
         public abstract void OnNext(TSource value);
 
@@ -76,7 +76,7 @@ namespace System.Reactive
 
         public void SetResource(IDisposable resource)
         {
-            Disposable.SetSingle(ref _disposable, resource);
+            _disposable.Disposable = resource;
         }
 
         public void Dispose()
@@ -88,7 +88,7 @@ namespace System.Reactive
         {
             if (disposing)
             {
-                Disposable.Dispose(ref _disposable);
+                _disposable.Dispose();
             }
         }
     }

+ 11 - 11
Rx.NET/Source/src/System.Reactive/Internal/ScheduledObserver.cs

@@ -25,7 +25,7 @@ namespace System.Reactive
         private readonly IObserver<T> _observer;
         private readonly IScheduler _scheduler;
         private readonly ISchedulerLongRunning? _longRunning;
-        private IDisposable? _disposable;
+        private SerialDisposableValue _disposable;
 
         public ScheduledObserver(IScheduler scheduler, IObserver<T> observer)
         {
@@ -70,11 +70,11 @@ namespace System.Reactive
                     {
                         _dispatcherJob = _longRunning!.ScheduleLongRunning(Dispatch); // NB: Only reachable when long-running.
 
-                        Disposable.TrySetSerial(ref _disposable, StableCompositeDisposable.Create
+                        _disposable.Disposable = StableCompositeDisposable.Create
                         (
                             _dispatcherJob,
                             _dispatcherEventRelease!
-                        ));
+                        );
                     }
                 }
             }
@@ -198,7 +198,7 @@ namespace System.Reactive
 
             if (isOwner)
             {
-                Disposable.TrySetSerial(ref _disposable, _scheduler.Schedule<object?>(null, Run));
+                _disposable.Disposable = _scheduler.Schedule<object?>(null, Run);
             }
         }
 
@@ -317,14 +317,14 @@ namespace System.Reactive
 
             if (disposing)
             {
-                Disposable.Dispose(ref _disposable);
+                _disposable.Dispose();
             }
         }
     }
 
     internal sealed class ObserveOnObserver<T> : ScheduledObserver<T>
     {
-        private IDisposable? _run;
+        private SingleAssignmentDisposableValue _run;
 
         public ObserveOnObserver(IScheduler scheduler, IObserver<T> observer)
             : base(scheduler, observer)
@@ -334,7 +334,7 @@ namespace System.Reactive
 
         public void Run(IObservable<T> source)
         {
-            Disposable.SetSingle(ref _run, source.SubscribeSafe(this));
+            _run.Disposable = source.SubscribeSafe(this);
         }
 
         protected override void OnNextCore(T value)
@@ -361,7 +361,7 @@ namespace System.Reactive
 
             if (disposing)
             {
-                Disposable.Dispose(ref _run);
+                _run.Dispose();
             }
         }
     }
@@ -626,7 +626,7 @@ namespace System.Reactive
         /// <summary>
         /// The disposable tracking the drain task.
         /// </summary>
-        private IDisposable? _drainTask;
+        private SingleAssignmentDisposableValue _drainTask;
 
         public ObserveOnObserverLongRunning(ISchedulerLongRunning scheduler, IObserver<TSource> observer) : base(observer)
         {
@@ -660,7 +660,7 @@ namespace System.Reactive
             if (Volatile.Read(ref _runDrainOnce) == 0
                 && Interlocked.CompareExchange(ref _runDrainOnce, 1, 0) == 0)
             {
-                Disposable.SetSingle(ref _drainTask, _scheduler.ScheduleLongRunning(this, DrainLongRunning));
+                _drainTask.Disposable = _scheduler.ScheduleLongRunning(this, DrainLongRunning);
             }
 
             // Indicate more work is to be done by the drain loop
@@ -689,7 +689,7 @@ namespace System.Reactive
                 Monitor.Pulse(_suspendGuard);
             }
             // Cancel the drain task handle.
-            Disposable.Dispose(ref _drainTask);
+            _drainTask.Dispose();
             base.Dispose(disposing);
         }
 

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Internal/Sink.cs

@@ -16,7 +16,7 @@ namespace System.Reactive
 
     internal abstract class Sink<TTarget> : ISink<TTarget>, IDisposable
     {
-        private IDisposable? _upstream;
+        private SingleAssignmentDisposableValue _upstream;
         private volatile IObserver<TTarget> _observer;
 
         protected Sink(IObserver<TTarget> observer)
@@ -41,7 +41,7 @@ namespace System.Reactive
             //Sink is internal so this can pretty much be enforced.
             //_observer = NopObserver<TTarget>.Instance;
 
-            Disposable.Dispose(ref _upstream);
+            _upstream.Dispose();
         }
 
         public void ForwardOnNext(TTarget value)
@@ -63,12 +63,12 @@ namespace System.Reactive
 
         protected void SetUpstream(IDisposable upstream)
         {
-            Disposable.SetSingle(ref _upstream, upstream);
+            _upstream.Disposable = upstream;
         }
 
         protected void DisposeUpstream()
         {
-            Disposable.Dispose(ref _upstream);
+            _upstream.Dispose();
         }
     }
 

+ 5 - 5
Rx.NET/Source/src/System.Reactive/Internal/SystemClock.Default.cs

@@ -39,7 +39,7 @@ namespace System.Reactive.PlatformServices
     public class PeriodicTimerSystemClockMonitor : INotifySystemClockChanged
     {
         private readonly TimeSpan _period;
-        private IDisposable? _timer;
+        private SerialDisposableValue _timer;
 
         /// <summary>
         /// Use the Unix milliseconds for the current time
@@ -78,13 +78,13 @@ namespace System.Reactive.PlatformServices
             {
                 _systemClockChanged -= value;
 
-                Disposable.TrySetSerial(ref _timer, Disposable.Empty);
+                _timer.Disposable = Disposable.Empty;
             }
         }
 
         private void NewTimer()
         {
-            Disposable.TrySetSerial(ref _timer, Disposable.Empty);
+            _timer.Disposable = Disposable.Empty;
 
             var n = 0L;
             for (; ; )
@@ -92,13 +92,13 @@ namespace System.Reactive.PlatformServices
                 var now = SystemClock.UtcNow.ToUnixTimeMilliseconds();
                 Interlocked.Exchange(ref _lastTimeUnixMillis, now);
 
-                Disposable.TrySetSerial(ref _timer, ConcurrencyAbstractionLayer.Current.StartPeriodicTimer(TimeChanged, _period));
+                _timer.Disposable = ConcurrencyAbstractionLayer.Current.StartPeriodicTimer(TimeChanged, _period);
 
                 if (Math.Abs(SystemClock.UtcNow.ToUnixTimeMilliseconds() - now) <= SyncMaxDelta)
                 {
                     break;
                 }
-                if (Volatile.Read(ref _timer) == Disposable.Empty)
+                if (_timer.Disposable == Disposable.Empty)
                 {
                     break;
                 }

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Joins/JoinObserver.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Joins
         private readonly IObservable<T> _source;
         private readonly Action<Exception> _onError;
         private readonly List<ActivePlan> _activePlans;
-        private IDisposable? _subscription;
+        private SingleAssignmentDisposableValue _subscription;
         private bool _isDisposed;
 
         public JoinObserver(IObservable<T> source, Action<Exception> onError)
@@ -41,7 +41,7 @@ namespace System.Reactive.Joins
         public void Subscribe(object gate)
         {
             _gate = gate;
-            Disposable.SetSingle(ref _subscription, _source.Materialize().SubscribeSafe(this));
+            _subscription.Disposable = _source.Materialize().SubscribeSafe(this);
         }
 
         public void Dequeue()
@@ -95,7 +95,7 @@ namespace System.Reactive.Joins
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _subscription);
+                    _subscription.Dispose();
                 }
 
                 _isDisposed = true;

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/AppendPrepend.cs

@@ -105,7 +105,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 private readonly TSource _value;
                 private readonly IScheduler _scheduler;
                 private readonly bool _append;
-                private IDisposable? _schedulerDisposable;
+                private SingleAssignmentDisposableValue _schedulerDisposable;
 
                 public _(SingleValue parent, IObserver<TSource> observer)
                     : base(observer)
@@ -136,7 +136,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     if (_append)
                     {
                         var disposable = _scheduler.ScheduleAction(this, AppendValue);
-                        Disposable.TrySetSingle(ref _schedulerDisposable, disposable);
+                        _schedulerDisposable.Disposable = disposable;
                     }
                     else
                     {
@@ -154,7 +154,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _schedulerDisposable);
+                        _schedulerDisposable.Dispose();
                     }
                     base.Dispose(disposing);
                 }

+ 15 - 15
Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs

@@ -270,7 +270,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 private readonly IScheduler _scheduler;
                 private readonly object _gate = new object();
                 private readonly Queue<List<TSource>> _q = new Queue<List<TSource>>();
-                private IDisposable? _timerSerial;
+                private SerialDisposableValue _timerSerial;
 
                 public _(TimeSliding parent, IObserver<IList<TSource>> observer)
                     : base(observer)
@@ -299,7 +299,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _timerSerial);
+                        _timerSerial.Dispose();
                     }
                     base.Dispose(disposing);
                 }
@@ -314,7 +314,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     var m = new SingleAssignmentDisposable();
 
-                    Disposable.TrySetSerial(ref _timerSerial, m);
+                    _timerSerial.Disposable = m;
 
                     var isSpan = false;
                     var isShift = false;
@@ -443,11 +443,11 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                 }
 
-                private IDisposable? _periodicDisposable;
+                private SingleAssignmentDisposableValue _periodicDisposable;
 
                 public void Run(TimeHopping parent)
                 {
-                    Disposable.SetSingle(ref _periodicDisposable, parent._scheduler.SchedulePeriodic(this, parent._timeSpan, static @this => @this.Tick()));
+                    _periodicDisposable.Disposable = parent._scheduler.SchedulePeriodic(this, parent._timeSpan, static @this => @this.Tick());
                     Run(parent._source);
                 }
 
@@ -455,7 +455,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _periodicDisposable);
+                        _periodicDisposable.Dispose();
                     }
                     base.Dispose(disposing);
                 }
@@ -529,7 +529,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     _parent = parent;
                 }
 
-                private IDisposable? _timerSerial;
+                private SerialDisposableValue _timerSerial;
                 private int _n;
                 private int _windowId;
 
@@ -547,7 +547,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _timerSerial);
+                        _timerSerial.Dispose();
                     }
 
                     base.Dispose(disposing);
@@ -556,7 +556,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 private void CreateTimer(int id)
                 {
                     var m = new SingleAssignmentDisposable();
-                    Disposable.TrySetSerial(ref _timerSerial, m);
+                    _timerSerial.Disposable = m;
 
                     m.Disposable = _parent._scheduler.ScheduleAction((@this: this, id), _parent._timeSpan, static tuple => [email protected](tuple.id));
                 }
@@ -654,7 +654,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 private readonly Func<IObservable<TBufferClosing>> _bufferClosingSelector;
 
                 private List<TSource> _buffer = new List<TSource>();
-                private IDisposable? _bufferClosingSerialDisposable;
+                private SerialDisposableValue _bufferClosingSerialDisposable;
 
                 public _(Selector parent, IObserver<IList<TSource>> observer)
                     : base(observer)
@@ -673,7 +673,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _bufferClosingSerialDisposable);
+                        _bufferClosingSerialDisposable.Dispose();
                     }
                     base.Dispose(disposing);
                 }
@@ -695,7 +695,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
 
                     var closingObserver = new BufferClosingObserver(this);
-                    Disposable.TrySetSerial(ref _bufferClosingSerialDisposable, closingObserver);
+                    _bufferClosingSerialDisposable.Disposable = closingObserver;
                     closingObserver.SetResource(bufferClose.SubscribeSafe(closingObserver));
                 }
 
@@ -786,7 +786,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 private readonly object _gate = new object();
 
                 private List<TSource> _buffer = new List<TSource>();
-                private IDisposable? _boundariesDisposable;
+                private SingleAssignmentDisposableValue _boundariesDisposable;
 
                 public _(IObserver<IList<TSource>> observer)
                     : base(observer)
@@ -796,14 +796,14 @@ namespace System.Reactive.Linq.ObservableImpl
                 public void Run(Boundaries parent)
                 {
                     Run(parent._source);
-                    Disposable.SetSingle(ref _boundariesDisposable, parent._bufferBoundaries.SubscribeSafe(new BufferClosingObserver(this)));
+                    _boundariesDisposable.Disposable = parent._bufferBoundaries.SubscribeSafe(new BufferClosingObserver(this));
                 }
 
                 protected override void Dispose(bool disposing)
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _boundariesDisposable);
+                        _boundariesDisposable.Dispose();
                     }
 
                     base.Dispose(disposing);

+ 8 - 8
Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs

@@ -39,8 +39,8 @@ namespace System.Reactive.Linq.ObservableImpl
                 _resultSelector = resultSelector;
             }
 
-            private IDisposable? _firstDisposable;
-            private IDisposable? _secondDisposable;
+            private SingleAssignmentDisposableValue _firstDisposable;
+            private SingleAssignmentDisposableValue _secondDisposable;
 
             public void Run(IObservable<TFirst> first, IObservable<TSecond> second)
             {
@@ -50,16 +50,16 @@ namespace System.Reactive.Linq.ObservableImpl
                 fstO.SetOther(sndO);
                 sndO.SetOther(fstO);
 
-                Disposable.SetSingle(ref _firstDisposable, first.SubscribeSafe(fstO));
-                Disposable.SetSingle(ref _secondDisposable, second.SubscribeSafe(sndO));
+                _firstDisposable.Disposable = first.SubscribeSafe(fstO);
+                _secondDisposable.Disposable = second.SubscribeSafe(sndO);
             }
 
             protected override void Dispose(bool disposing)
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _firstDisposable);
-                    Disposable.Dispose(ref _secondDisposable);
+                    _firstDisposable.Dispose();
+                    _secondDisposable.Dispose();
                 }
 
                 base.Dispose(disposing);
@@ -131,7 +131,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         }
                         else
                         {
-                            Disposable.Dispose(ref _parent._firstDisposable);
+                            _parent._firstDisposable.Dispose();
                         }
                     }
                 }
@@ -203,7 +203,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         }
                         else
                         {
-                            Disposable.Dispose(ref _parent._secondDisposable);
+                            _parent._secondDisposable.Dispose();
                         }
                     }
                 }

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Linq/Observable/ConcatMany.cs

@@ -38,7 +38,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private readonly ConcurrentQueue<IObservable<T>> _queue;
             private readonly InnerObserver _innerObserver;
 
-            private IDisposable? _upstream;
+            private SingleAssignmentDisposableValue _upstream;
             private int _trampoline;
             private Exception? _error;
             private bool _done;
@@ -53,7 +53,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             internal void OnSubscribe(IDisposable d)
             {
-                Disposable.SetSingle(ref _upstream, d);
+                _upstream.Disposable = d;
             }
 
             public void Dispose()
@@ -64,12 +64,12 @@ namespace System.Reactive.Linq.ObservableImpl
 
             private void DisposeMain()
             {
-                Disposable.Dispose(ref _upstream);
+                _upstream.Dispose();
             }
 
             private bool IsDisposed()
             {
-                return Disposable.GetIsDisposed(ref _upstream);
+                return _upstream.IsDisposed;
             }
 
             public void OnCompleted()

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs

@@ -607,20 +607,20 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
 
                 private bool _atEnd;
-                private IDisposable? _subscription;
+                private SingleAssignmentDisposableValue _subscription;
 
                 public void Run(TParent parent)
                 {
                     _atEnd = false;
 
-                    Disposable.SetSingle(ref _subscription, RunCore(parent));
+                    _subscription.Disposable = RunCore(parent);
                 }
 
                 protected override void Dispose(bool disposing)
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _subscription);
+                        _subscription.Dispose();
                         _delays.Dispose();
                     }
                     base.Dispose(disposing);
@@ -663,7 +663,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     lock (_gate)
                     {
                         _atEnd = true;
-                        Disposable.Dispose(ref _subscription);
+                        _subscription.Dispose();
 
                         CheckDone();
                     }

+ 8 - 8
Rx.NET/Source/src/System.Reactive/Linq/Observable/Generate.cs

@@ -197,18 +197,18 @@ namespace System.Reactive.Linq.ObservableImpl
                 private bool _hasResult;
                 private TResult? _result;
 
-                private IDisposable? _timerDisposable;
+                private MultipleAssignmentDisposableValue _timerDisposable;
 
                 public void Run(IScheduler outerScheduler, TState initialState)
                 {
                     var timer = new SingleAssignmentDisposable();
-                    Disposable.TrySetMultiple(ref _timerDisposable, timer);
+                    _timerDisposable.Disposable = timer;
                     timer.Disposable = outerScheduler.Schedule((@this: this, initialState), static (scheduler, tuple) => [email protected](scheduler, tuple.initialState));
                 }
 
                 protected override void Dispose(bool disposing)
                 {
-                    Disposable.Dispose(ref _timerDisposable);
+                    _timerDisposable.Dispose();
                     base.Dispose(disposing);
                 }
 
@@ -253,7 +253,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
 
                     var timer = new SingleAssignmentDisposable();
-                    Disposable.TrySetMultiple(ref _timerDisposable, timer);
+                    _timerDisposable.Disposable = timer;
                     timer.Disposable = self.Schedule((@this: this, state), time, static (scheduler, tuple) => [email protected](scheduler, tuple.state));
 
                     return Disposable.Empty;
@@ -306,18 +306,18 @@ namespace System.Reactive.Linq.ObservableImpl
                 private bool _hasResult;
                 private TResult? _result;
 
-                private IDisposable? _timerDisposable;
+                private MultipleAssignmentDisposableValue _timerDisposable;
 
                 public void Run(IScheduler outerScheduler, TState initialState)
                 {
                     var timer = new SingleAssignmentDisposable();
-                    Disposable.TrySetMultiple(ref _timerDisposable, timer);
+                    _timerDisposable.Disposable = timer;
                     timer.Disposable = outerScheduler.Schedule((@this: this, initialState), static (scheduler, tuple) => [email protected](scheduler, tuple.initialState));
                 }
 
                 protected override void Dispose(bool disposing)
                 {
-                    Disposable.Dispose(ref _timerDisposable);
+                    _timerDisposable.Dispose();
                     base.Dispose(disposing);
                 }
 
@@ -362,7 +362,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
 
                     var timer = new SingleAssignmentDisposable();
-                    Disposable.TrySetMultiple(ref _timerDisposable, timer);
+                    _timerDisposable.Disposable = timer;
                     timer.Disposable = self.Schedule((@this: this, state), time, static (scheduler, tuple) => [email protected](scheduler, tuple.state));
 
                     return Disposable.Empty;

+ 5 - 5
Rx.NET/Source/src/System.Reactive/Linq/Observable/GetEnumerator.cs

@@ -17,7 +17,7 @@ namespace System.Reactive.Linq.ObservableImpl
         private Exception? _error;
         private bool _done;
         private bool _disposed;
-        private IDisposable? _subscription;
+        private SingleAssignmentDisposableValue _subscription;
 
         private readonly SemaphoreSlim _gate;
 
@@ -32,7 +32,7 @@ namespace System.Reactive.Linq.ObservableImpl
             //
             // [OK] Use of unsafe Subscribe: non-pretentious exact mirror with the dual GetEnumerator method.
             //
-            Disposable.TrySetSingle(ref _subscription, source.Subscribe/*Unsafe*/(this));
+            _subscription.Disposable = source.Subscribe/*Unsafe*/(this);
             return this;
         }
 
@@ -45,14 +45,14 @@ namespace System.Reactive.Linq.ObservableImpl
         public void OnError(Exception error)
         {
             _error = error;
-            Disposable.Dispose(ref _subscription);
+            _subscription.Dispose();
             _gate.Release();
         }
 
         public void OnCompleted()
         {
             _done = true;
-            Disposable.Dispose(ref _subscription);
+            _subscription.Dispose();
             _gate.Release();
         }
 
@@ -84,7 +84,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
         public void Dispose()
         {
-            Disposable.Dispose(ref _subscription);
+            _subscription.Dispose();
 
             _disposed = true;
             _gate.Release();

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/Multicast.cs

@@ -26,7 +26,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
         internal sealed class _ : IdentitySink<TResult>
         {
-            private IDisposable? _connection;
+            private SingleAssignmentDisposableValue _connection;
 
             public _(IObserver<TResult> observer)
                 : base(observer)
@@ -51,14 +51,14 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
 
                 Run(observable);
-                Disposable.SetSingle(ref _connection, connectable.Connect());
+                _connection.Disposable = connectable.Connect();
             }
 
             protected override void Dispose(bool disposing)
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _connection);
+                    _connection.Dispose();
                 }
                 
                 base.Dispose(disposing);

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/PushToPullAdapter.cs

@@ -32,7 +32,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
     internal abstract class PushToPullSink<TSource, TResult> : IObserver<TSource>, IEnumerator<TResult>
     {
-        private IDisposable? _upstream;
+        private SingleAssignmentDisposableValue _upstream;
 
         public abstract void OnNext(TSource value);
         public abstract void OnError(Exception error);
@@ -76,12 +76,12 @@ namespace System.Reactive.Linq.ObservableImpl
 
         public void Dispose()
         {
-            Disposable.Dispose(ref _upstream);
+            _upstream.Dispose();
         }
 
         public void SetUpstream(IDisposable d)
         {
-            Disposable.SetSingle(ref _upstream, d);
+            _upstream.Disposable = d;
         }
     }
 }

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Linq/Observable/RefCount.cs

@@ -83,13 +83,13 @@ namespace System.Reactive.Linq.ObservableImpl
                     Run(_parent._source);
 
                     // then connect the source if necessary
-                    if (doConnect && !Disposable.GetIsDisposed(ref conn._disposable))
+                    if (doConnect && !conn._disposable.IsDisposed)
                     {
                         // this makes sure if the connection ends synchronously
                         // only the currently known connection is affected
                         // and a connection from a concurrent reconnection won't
                         // interfere
-                        Disposable.SetSingle(ref conn._disposable, _parent._source.Connect());
+                        conn._disposable.Disposable = _parent._source.Connect();
                     }
                 }
 
@@ -119,7 +119,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         }
 
                         // disconnect
-                        Disposable.Dispose(ref targetConnection._disposable);
+                        targetConnection._disposable.Dispose();
                     }
                 }
             }
@@ -131,7 +131,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private sealed class RefConnection
             {
                 internal int _count;
-                internal IDisposable? _disposable;
+                internal SingleAssignmentDisposableValue _disposable;
             }
         }
 

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/RepeatWhen.cs

@@ -48,7 +48,7 @@ namespace System.Reactive.Linq.ObservableImpl
             var parent = new MainObserver(observer, _source, new RedoSerializedObserver<object>(completeSignals));
 
             var d = redo.SubscribeSafe(parent.HandlerConsumer);
-            Disposable.SetSingle(ref parent.HandlerUpstream, d);
+            parent._handlerUpstream.Disposable = d;
 
             parent.HandlerNext();
 
@@ -62,7 +62,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             internal readonly HandlerObserver HandlerConsumer;
 
-            internal IDisposable? HandlerUpstream;
+            internal SingleAssignmentDisposableValue _handlerUpstream;
 
             private IDisposable? _upstream;
             private int _trampoline;
@@ -81,7 +81,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 if (disposing)
                 {
                     Disposable.Dispose(ref _upstream);
-                    Disposable.Dispose(ref HandlerUpstream);
+                    _handlerUpstream.Dispose();
                 }
 
                 base.Dispose(disposing);

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/RetryWhen.cs

@@ -49,7 +49,7 @@ namespace System.Reactive.Linq.ObservableImpl
             var parent = new MainObserver(observer, _source, new RedoSerializedObserver<Exception>(errorSignals));
 
             var d = redo.SubscribeSafe(parent.HandlerConsumer);
-            Disposable.SetSingle(ref parent.HandlerUpstream, d);
+            parent.HandlerUpstream.Disposable = d;
 
             parent.HandlerNext();
 
@@ -63,7 +63,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             internal readonly HandlerObserver HandlerConsumer;
             private IDisposable? _upstream;
-            internal IDisposable? HandlerUpstream;
+            internal SingleAssignmentDisposableValue HandlerUpstream;
             private int _trampoline;
             private int _halfSerializer;
             private Exception? _error;
@@ -80,7 +80,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 if (disposing)
                 {
                     Disposable.Dispose(ref _upstream);
-                    Disposable.Dispose(ref HandlerUpstream);
+                    HandlerUpstream.Dispose();
                 }
 
                 base.Dispose(disposing);

+ 12 - 12
Rx.NET/Source/src/System.Reactive/Linq/Observable/Sample.cs

@@ -31,8 +31,8 @@ namespace System.Reactive.Linq.ObservableImpl
             {
             }
 
-            private IDisposable? _sourceDisposable;
-            private IDisposable? _samplerDisposable;
+            private SingleAssignmentDisposableValue _sourceDisposable;
+            private SingleAssignmentDisposableValue _samplerDisposable;
 
             private bool _hasValue;
             private TSource? _value;
@@ -41,17 +41,17 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void Run(Sample<TSource, TSample> parent)
             {
-                Disposable.SetSingle(ref _sourceDisposable, parent._source.SubscribeSafe(this));
+                _sourceDisposable.Disposable = parent._source.SubscribeSafe(this);
 
-                Disposable.SetSingle(ref _samplerDisposable, parent._sampler.SubscribeSafe(new SampleObserver(this)));
+                _samplerDisposable.Disposable = parent._sampler.SubscribeSafe(new SampleObserver(this));
             }
 
             protected override void Dispose(bool disposing)
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _sourceDisposable);
-                    Disposable.Dispose(ref _samplerDisposable);
+                    _sourceDisposable.Dispose();
+                    _samplerDisposable.Dispose();
                 }
 
                 base.Dispose(disposing);
@@ -86,7 +86,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
                     else
                     {
-                        Disposable.Dispose(ref _sourceDisposable);
+                        _sourceDisposable.Dispose();
                     }
                 }
             }
@@ -144,7 +144,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         }
                         else
                         {
-                            Disposable.Dispose(ref _parent._samplerDisposable);
+                            _parent._samplerDisposable.Dispose();
                         }
                     }
                 }
@@ -178,7 +178,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
             }
 
-            private IDisposable? _sourceDisposable;
+            private SingleAssignmentDisposableValue _sourceDisposable;
 
             private bool _hasValue;
             private TSource? _value;
@@ -186,7 +186,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void Run(Sample<TSource> parent)
             {
-                Disposable.SetSingle(ref _sourceDisposable, parent._source.SubscribeSafe(this));
+                _sourceDisposable.Disposable = parent._source.SubscribeSafe(this);
 
                 SetUpstream(parent._scheduler.SchedulePeriodic(parent._interval, Tick));
             }
@@ -195,7 +195,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _sourceDisposable);
+                    _sourceDisposable.Dispose();
                 }
 
                 base.Dispose(disposing);
@@ -240,7 +240,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 lock (_gate)
                 {
                     _atEnd = true;
-                    Disposable.Dispose(ref _sourceDisposable);
+                    _sourceDisposable.Dispose();
                 }
             }
         }

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/SequenceEqual.cs

@@ -46,19 +46,19 @@ namespace System.Reactive.Linq.ObservableImpl
                 private bool _donel;
                 private bool _doner;
 
-                private IDisposable? _second;
+                private SingleAssignmentDisposableValue _second;
 
                 public void Run(Observable parent)
                 {
                     SetUpstream(parent._first.SubscribeSafe(new FirstObserver(this)));
-                    Disposable.SetSingle(ref _second, parent._second.SubscribeSafe(new SecondObserver(this)));
+                    _second.Disposable = parent._second.SubscribeSafe(new SecondObserver(this));
                 }
 
                 protected override void Dispose(bool disposing)
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _second);
+                        _second.Dispose();
                     }
 
                     base.Dispose(disposing);

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/Skip.cs

@@ -105,19 +105,19 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                 }
 
-                private IDisposable? _sourceDisposable;
+                private SingleAssignmentDisposableValue _sourceDisposable;
 
                 public void Run(Time parent)
                 {
                     SetUpstream(parent._scheduler.ScheduleAction(this, parent._duration, state => state.Tick()));
-                    Disposable.SetSingle(ref _sourceDisposable, parent._source.SubscribeSafe(this));
+                    _sourceDisposable.Disposable = parent._source.SubscribeSafe(this);
                 }
 
                 protected override void Dispose(bool disposing)
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _sourceDisposable);
+                        _sourceDisposable.Dispose();
                     }
 
                     base.Dispose(disposing);

+ 9 - 9
Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipUntil.cs

@@ -24,7 +24,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
         internal sealed class _ : IdentitySink<TSource>
         {
-            private IDisposable? _otherDisposable;
+            private SingleAssignmentDisposableValue _otherDisposable;
             private bool _forward;
             private int _halfSerializer;
             private Exception? _error;
@@ -36,7 +36,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void Run(SkipUntil<TSource, TOther> parent)
             {
-                Disposable.TrySetSingle(ref _otherDisposable, parent._other.Subscribe(new OtherObserver(this)));
+                _otherDisposable.Disposable = parent._other.Subscribe(new OtherObserver(this));
                 Run(parent._source);
             }
 
@@ -44,9 +44,9 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    if (!Disposable.GetIsDisposed(ref _otherDisposable))
+                    if (!_otherDisposable.IsDisposed)
                     {
-                        Disposable.Dispose(ref _otherDisposable);
+                        _otherDisposable.Dispose();
                     }
                 }
 
@@ -94,9 +94,9 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 public void Dispose()
                 {
-                    if (!Disposable.GetIsDisposed(ref _parent._otherDisposable))
+                    if (!_parent._otherDisposable.IsDisposed)
                     {
-                        Disposable.Dispose(ref _parent._otherDisposable);
+                        _parent._otherDisposable.Dispose();
                     }
                 }
 
@@ -164,11 +164,11 @@ namespace System.Reactive.Linq.ObservableImpl
             {
             }
 
-            private IDisposable? _task;
+            private SingleAssignmentDisposableValue _task;
 
             public void Run(SkipUntil<TSource> parent)
             {
-                Disposable.SetSingle(ref _task, parent._scheduler.ScheduleAction(this, parent._startTime, static state => state.Tick()));
+                _task.Disposable = parent._scheduler.ScheduleAction(this, parent._startTime, static state => state.Tick());
                 Run(parent._source);
             }
 
@@ -176,7 +176,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _task);
+                    _task.Dispose();
                 }
 
                 base.Dispose(disposing);

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs

@@ -28,7 +28,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
             }
 
-            private IDisposable? _innerSerialDisposable;
+            private SerialDisposableValue _innerSerialDisposable;
             private bool _isStopped;
             private ulong _latest;
             private bool _hasLatest;
@@ -37,7 +37,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _innerSerialDisposable);
+                    _innerSerialDisposable.Dispose();
                 }
 
                 base.Dispose(disposing);
@@ -55,7 +55,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 var innerObserver = new InnerObserver(this, id);
 
-                Disposable.TrySetSerial(ref _innerSerialDisposable, innerObserver);
+                _innerSerialDisposable.Disposable = innerObserver;
                 innerObserver.SetResource(value.SubscribeSafe(innerObserver));
             }
 

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/Take.cs

@@ -112,11 +112,11 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                 }
 
-                private IDisposable? _task;
+                private SingleAssignmentDisposableValue _task;
 
                 public void Run(Time parent)
                 {
-                    Disposable.SetSingle(ref _task, parent._scheduler.ScheduleAction(this, parent._duration, state => state.Tick()));
+                    _task.Disposable = parent._scheduler.ScheduleAction(this, parent._duration, state => state.Tick());
                     Run(parent._source);
                 }
 
@@ -124,7 +124,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _task);
+                        _task.Dispose();
                     }
 
                     base.Dispose(disposing);

+ 2 - 2
Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLast.cs

@@ -70,7 +70,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var longRunning = _loopScheduler.AsLongRunning();
                     if (longRunning != null)
                     {
-                        Disposable.SetSingle(ref _loopDisposable, longRunning.ScheduleLongRunning(this, static (@this, c) => @this.Loop(c)));
+                        Disposable.TrySetSingle(ref _loopDisposable, longRunning.ScheduleLongRunning(this, static (@this, c) => @this.Loop(c)));
                     }
                     else
                     {
@@ -186,7 +186,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var longRunning = _loopScheduler.AsLongRunning();
                     if (longRunning != null)
                     {
-                        Disposable.SetSingle(ref _loopDisposable, longRunning.ScheduleLongRunning(this, static (@this, c) => @this.Loop(c)));
+                        Disposable.TrySetSingle(ref _loopDisposable, longRunning.ScheduleLongRunning(this, static (@this, c) => @this.Loop(c)));
                     }
                     else
                     {

+ 8 - 8
Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeUntil.cs

@@ -24,7 +24,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
         internal sealed class _ : IdentitySink<TSource>
         {
-            private IDisposable? _otherDisposable;
+            private SingleAssignmentDisposableValue _otherDisposable;
             private int _halfSerializer;
             private Exception? _error;
 
@@ -35,7 +35,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void Run(TakeUntil<TSource, TOther> parent)
             {
-                Disposable.SetSingle(ref _otherDisposable, parent._other.Subscribe(new OtherObserver(this)));
+                _otherDisposable.Disposable = parent._other.Subscribe(new OtherObserver(this));
                 Run(parent._source);
             }
 
@@ -43,9 +43,9 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    if (!Disposable.GetIsDisposed(ref _otherDisposable))
+                    if (!_otherDisposable.IsDisposed)
                     {
-                        Disposable.Dispose(ref _otherDisposable);
+                        _otherDisposable.Dispose();
                     }
                 }
 
@@ -79,7 +79,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 public void OnCompleted()
                 {
                     // Completion doesn't mean termination in Rx.NET for this operator
-                    Disposable.Dispose(ref _parent._otherDisposable);
+                    _parent._otherDisposable.Dispose();
                 }
 
                 public void OnError(Exception error)
@@ -134,7 +134,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
         internal sealed class _ : IdentitySink<TSource>
         {
-            private IDisposable? _timerDisposable;
+            private SingleAssignmentDisposableValue _timerDisposable;
             private int _wip;
             private Exception? _error;
 
@@ -145,7 +145,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void Run(TakeUntil<TSource> parent)
             {
-                Disposable.SetSingle(ref _timerDisposable, parent._scheduler.ScheduleAction(this, parent._endTime, state => state.Tick()));
+                _timerDisposable.Disposable = parent._scheduler.ScheduleAction(this, parent._endTime, state => state.Tick());
                 Run(parent._source);
             }
 
@@ -153,7 +153,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _timerDisposable);
+                    _timerDisposable.Dispose();
                 }
 
                 base.Dispose(disposing);

+ 12 - 12
Rx.NET/Source/src/System.Reactive/Linq/Observable/Throttle.cs

@@ -39,14 +39,14 @@ namespace System.Reactive.Linq.ObservableImpl
 
             private TSource? _value;
             private bool _hasValue;
-            private IDisposable? _serialCancelable;
+            private SerialDisposableValue _serialCancelable;
             private ulong _id;
 
             protected override void Dispose(bool disposing)
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _serialCancelable);
+                    _serialCancelable.Dispose();
                 }
 
                 base.Dispose(disposing);
@@ -64,8 +64,8 @@ namespace System.Reactive.Linq.ObservableImpl
                     currentid = _id;
                 }
 
-                Disposable.TrySetSerial(ref _serialCancelable, null);
-                Disposable.TrySetSerial(ref _serialCancelable, _scheduler.ScheduleAction((@this: this, currentid), _dueTime, static tuple => [email protected](tuple.currentid)));
+                _serialCancelable.Disposable = null;
+                _serialCancelable.Disposable = _scheduler.ScheduleAction((@this: this, currentid), _dueTime, static tuple => [email protected](tuple.currentid));
             }
 
             private void Propagate(ulong currentid)
@@ -83,7 +83,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public override void OnError(Exception error)
             {
-                Disposable.Dispose(ref _serialCancelable);
+                _serialCancelable.Dispose();
 
                 lock (_gate)
                 {
@@ -96,7 +96,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public override void OnCompleted()
             {
-                Disposable.Dispose(ref _serialCancelable);
+                _serialCancelable.Dispose();
 
                 lock (_gate)
                 {
@@ -142,14 +142,14 @@ namespace System.Reactive.Linq.ObservableImpl
 
             private TSource? _value;
             private bool _hasValue;
-            private IDisposable? _serialCancelable;
+            private SerialDisposableValue _serialCancelable;
             private ulong _id;
 
             protected override void Dispose(bool disposing)
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _serialCancelable);
+                    _serialCancelable.Dispose();
                 }
 
                 base.Dispose(disposing);
@@ -182,17 +182,17 @@ namespace System.Reactive.Linq.ObservableImpl
                     currentid = _id;
                 }
 
-                Disposable.TrySetSerial(ref _serialCancelable, null);
+                _serialCancelable.Disposable = null;
 
                 var newInnerObserver = new ThrottleObserver(this, value, currentid);
                 newInnerObserver.SetResource(throttle.SubscribeSafe(newInnerObserver));
 
-                Disposable.TrySetSerial(ref _serialCancelable, newInnerObserver);
+                _serialCancelable.Disposable = newInnerObserver;
             }
 
             public override void OnError(Exception error)
             {
-                Disposable.Dispose(ref _serialCancelable);
+                _serialCancelable.Dispose();
 
                 lock (_gate)
                 {
@@ -205,7 +205,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public override void OnCompleted()
             {
-                Disposable.Dispose(ref _serialCancelable);
+                _serialCancelable.Dispose();
 
                 lock (_gate)
                 {

+ 12 - 12
Rx.NET/Source/src/System.Reactive/Linq/Observable/Timeout.cs

@@ -36,8 +36,8 @@ namespace System.Reactive.Linq.ObservableImpl
                 private readonly IScheduler _scheduler;
 
                 private long _index;
-                private IDisposable? _mainDisposable;
-                private IDisposable? _otherDisposable;
+                private SingleAssignmentDisposableValue _mainDisposable;
+                private SingleAssignmentDisposableValue _otherDisposable;
                 private IDisposable? _timerDisposable;
 
                 public _(Relative parent, IObserver<TSource> observer)
@@ -52,15 +52,15 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     CreateTimer(0L);
 
-                    Disposable.SetSingle(ref _mainDisposable, source.SubscribeSafe(this));
+                    _mainDisposable.Disposable = source.SubscribeSafe(this);
                 }
 
                 protected override void Dispose(bool disposing)
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _mainDisposable);
-                        Disposable.Dispose(ref _otherDisposable);
+                        _mainDisposable.Dispose();
+                        _otherDisposable.Dispose();
                         Disposable.Dispose(ref _timerDisposable);
                     }
 
@@ -81,11 +81,11 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (Volatile.Read(ref _index) == idx && Interlocked.CompareExchange(ref _index, long.MaxValue, idx) == idx)
                     {
-                        Disposable.Dispose(ref _mainDisposable);
+                        _mainDisposable.Dispose();
 
                         var d = _other.Subscribe(GetForwarder());
 
-                        Disposable.SetSingle(ref _otherDisposable, d);
+                        _otherDisposable.Disposable = d;
                     }
                 }
 
@@ -150,7 +150,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 private readonly IObservable<TSource> _other;
 
-                private IDisposable? _serialDisposable;
+                private SerialDisposableValue _serialDisposable;
                 private int _wip;
 
                 public _(IObservable<TSource> other, IObserver<TSource> observer)
@@ -163,14 +163,14 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     SetUpstream(parent._scheduler.ScheduleAction(this, parent._dueTime, static @this => @this.Timeout()));
 
-                    Disposable.TrySetSingle(ref _serialDisposable, parent._source.SubscribeSafe(this));
+                    _serialDisposable.Disposable = parent._source.SubscribeSafe(this);
                 }
 
                 protected override void Dispose(bool disposing)
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _serialDisposable);
+                        _serialDisposable.Dispose();
                     }
 
                     base.Dispose(disposing);
@@ -180,7 +180,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (Interlocked.Increment(ref _wip) == 1)
                     {
-                        Disposable.TrySetSerial(ref _serialDisposable, _other.SubscribeSafe(GetForwarder()));
+                        _serialDisposable.Disposable = _other.SubscribeSafe(GetForwarder());
                     }
                 }
 
@@ -191,7 +191,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         ForwardOnNext(value);
                         if (Interlocked.Decrement(ref _wip) != 0)
                         {
-                            Disposable.TrySetSerial(ref _serialDisposable, _other.SubscribeSafe(GetForwarder()));
+                            _serialDisposable.Disposable = _other.SubscribeSafe(GetForwarder());
                         }
                     }
                 }

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/Observable/Using.cs

@@ -29,7 +29,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
             }
 
-            private IDisposable? _disposable;
+            private SingleAssignmentDisposableValue _disposable;
 
             public void Run(Using<TSource, TResource> parent)
             {
@@ -63,7 +63,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 // Run(). In the synchronous case this would else dispose
                 // the the resource before the source subscription.
                 Run(source);
-                Disposable.SetSingle(ref _disposable, disposable);
+                _disposable.Disposable = disposable;
             }
 
             protected override void Dispose(bool disposing)
@@ -72,7 +72,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _disposable);
+                    _disposable.Dispose();
                 }
             }
         }

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Linq/Observable/WithLatestFrom.cs

@@ -39,14 +39,14 @@ namespace System.Reactive.Linq.ObservableImpl
             private volatile bool _hasLatest;
             private TSecond? _latest;
 
-            private IDisposable? _secondDisposable;
+            private SingleAssignmentDisposableValue _secondDisposable;
 
             public void Run(IObservable<TFirst> first, IObservable<TSecond> second)
             {
                 var fstO = new FirstObserver(this);
                 var sndO = new SecondObserver(this);
 
-                Disposable.SetSingle(ref _secondDisposable, second.SubscribeSafe(sndO));
+                _secondDisposable.Disposable = second.SubscribeSafe(sndO);
                 SetUpstream(first.SubscribeSafe(fstO));
             }
 
@@ -54,7 +54,7 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    Disposable.Dispose(ref _secondDisposable);
+                    _secondDisposable.Dispose();
                 }
 
                 base.Dispose(disposing);
@@ -131,7 +131,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 public void OnCompleted()
                 {
-                    Disposable.Dispose(ref _parent._secondDisposable);
+                    _parent._secondDisposable.Dispose();
                 }
 
                 public void OnError(Exception error)

+ 16 - 16
Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.cs

@@ -38,10 +38,10 @@ namespace System.Reactive.Linq.ObservableImpl
                 private readonly object _gate;
 
                 private readonly FirstObserver _firstObserver;
-                private IDisposable? _firstDisposable;
+                private SingleAssignmentDisposableValue _firstDisposable;
 
                 private readonly SecondObserver _secondObserver;
-                private IDisposable? _secondDisposable;
+                private SingleAssignmentDisposableValue _secondDisposable;
 
                 public _(Func<TFirst, TSecond, TResult> resultSelector, IObserver<TResult> observer)
                     : base(observer)
@@ -59,16 +59,16 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 public void Run(IObservable<TFirst> first, IObservable<TSecond> second)
                 {
-                    Disposable.SetSingle(ref _firstDisposable, first.SubscribeSafe(_firstObserver));
-                    Disposable.SetSingle(ref _secondDisposable, second.SubscribeSafe(_secondObserver));
+                    _firstDisposable.Disposable = first.SubscribeSafe(_firstObserver);
+                    _secondDisposable.Disposable = second.SubscribeSafe(_secondObserver);
                 }
 
                 protected override void Dispose(bool disposing)
                 {
                     if (disposing)
                     {
-                        Disposable.Dispose(ref _firstDisposable);
-                        Disposable.Dispose(ref _secondDisposable);
+                        _firstDisposable.Dispose();
+                        _secondDisposable.Dispose();
 
                         // clearing the queue should happen under the lock
                         // as they are plain Queue<T>s, not concurrent queues.
@@ -154,7 +154,7 @@ namespace System.Reactive.Linq.ObservableImpl
                             }
                             else
                             {
-                                Disposable.Dispose(ref _parent._firstDisposable);
+                                _parent._firstDisposable.Dispose();
                             }
                         }
                     }
@@ -237,7 +237,7 @@ namespace System.Reactive.Linq.ObservableImpl
                             }
                             else
                             {
-                                Disposable.Dispose(ref _parent._secondDisposable);
+                                _parent._secondDisposable.Dispose();
                             }
                         }
                     }
@@ -605,7 +605,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             private Queue<TSource>[] _queues;
             private bool[] _isDone;
-            private IDisposable[]? _subscriptions;
+            private SingleAssignmentDisposableValue[]? _subscriptions;
 
             public void Run(IEnumerable<IObservable<TSource>> sources)
             {
@@ -621,14 +621,14 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 _isDone = new bool[N];
 
-                var subscriptions = new IDisposable[N];
+                var subscriptions = new SingleAssignmentDisposableValue[N];
 
                 if (Interlocked.CompareExchange(ref _subscriptions, subscriptions, null) == null)
                 {
                     for (var i = 0; i < N; i++)
                     {
                         var o = new SourceObserver(this, i);
-                        Disposable.SetSingle(ref subscriptions[i], srcs[i].SubscribeSafe(o));
+                        subscriptions[i].Disposable = srcs[i].SubscribeSafe(o);
                     }
                 }
             }
@@ -637,12 +637,12 @@ namespace System.Reactive.Linq.ObservableImpl
             {
                 if (disposing)
                 {
-                    var subscriptions = Interlocked.Exchange(ref _subscriptions, Array.Empty<IDisposable>());
-                    if (subscriptions != null && subscriptions != Array.Empty<IDisposable>())
+                    var subscriptions = Interlocked.Exchange(ref _subscriptions, Array.Empty<SingleAssignmentDisposableValue>());
+                    if (subscriptions != null && subscriptions != Array.Empty<SingleAssignmentDisposableValue>())
                     {
                         for (var i = 0; i < subscriptions.Length; i++)
                         {
-                            Disposable.Dispose(ref subscriptions[i]);
+                            subscriptions[i].Dispose();
                         }
 
                         lock (_gate)
@@ -703,9 +703,9 @@ namespace System.Reactive.Linq.ObservableImpl
                     else
                     {
                         var subscriptions = Volatile.Read(ref _subscriptions);
-                        if (subscriptions != null && subscriptions != Array.Empty<IDisposable>())
+                        if (subscriptions != null && subscriptions != Array.Empty<SingleAssignmentDisposableValue>())
                         {
-                            Disposable.Dispose(ref subscriptions[index]);
+                            subscriptions[index].Dispose();
                         }
                     }
                 }

+ 3 - 3
Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Creation.cs

@@ -141,7 +141,7 @@ namespace System.Reactive.Linq
                 private sealed class TaskDisposeCompletionObserver : IObserver<IDisposable>, IDisposable
                 {
                     private readonly IObserver<TResult> _observer;
-                    private IDisposable? _disposable;
+                    private SingleAssignmentDisposableValue _disposable;
 
                     public TaskDisposeCompletionObserver(IObserver<TResult> observer)
                     {
@@ -150,7 +150,7 @@ namespace System.Reactive.Linq
 
                     public void Dispose()
                     {
-                        Disposable.Dispose(ref _disposable);
+                        _disposable.Dispose();
                     }
 
                     public void OnCompleted()
@@ -164,7 +164,7 @@ namespace System.Reactive.Linq
 
                     public void OnNext(IDisposable value)
                     {
-                        Disposable.SetSingle(ref _disposable, value);
+                        _disposable.Disposable = value;
                     }
                 }