Explorar o código

Merge pull request #388 from Reactive-Extensions/SmallerLayouts

First steps to reduce operator object layouts
Bart J.F. De Smet %!s(int64=8) %!d(string=hai) anos
pai
achega
0c551b6055
Modificáronse 100 ficheiros con 6210 adicións e 5410 borrados
  1. 73 69
      Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.ObserveOn.cs
  2. 2 2
      Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs
  3. 29 0
      Rx.NET/Source/src/System.Reactive/Internal/Helpers.cs
  4. 4 8
      Rx.NET/Source/src/System.Reactive/Linq/GroupedObservable.cs
  5. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/AddRef.cs
  6. 119 55
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Aggregate.cs
  7. 6 6
      Rx.NET/Source/src/System.Reactive/Linq/Observable/All.cs
  8. 13 14
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Amb.cs
  9. 75 69
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Any.cs
  10. 2 5
      Rx.NET/Source/src/System.Reactive/Linq/Observable/AsObservable.cs
  11. 10 10
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Average.cs
  12. 490 478
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs
  13. 6 9
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Case.cs
  14. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Cast.cs
  15. 13 13
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Catch.cs
  16. 3 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Collect.cs
  17. 260 302
      Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.cs
  18. 11 13
      Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.tt
  19. 68 42
      Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs
  20. 2 5
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Concat.cs
  21. 6 4
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Contains.cs
  22. 83 75
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Count.cs
  23. 6 6
      Rx.NET/Source/src/System.Reactive/Linq/Observable/DefaultIfEmpty.cs
  24. 7 10
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Defer.cs
  25. 606 509
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs
  26. 28 17
      Rx.NET/Source/src/System.Reactive/Linq/Observable/DelaySubscription.cs
  27. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Dematerialize.cs
  28. 5 5
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Distinct.cs
  29. 9 5
      Rx.NET/Source/src/System.Reactive/Linq/Observable/DistinctUntilChanged.cs
  30. 191 48
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs
  31. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/DoWhile.cs
  32. 6 19
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAt.cs
  33. 61 0
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAtOrDefault.cs
  34. 6 9
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Empty.cs
  35. 9 9
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs
  36. 69 81
      Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstAsync.cs
  37. 120 0
      Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstOrDefaultAsync.cs
  38. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/For.cs
  39. 7 13
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ForEach.cs
  40. 3 3
      Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEvent.cs
  41. 19 7
      Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEventPattern.cs
  42. 266 200
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Generate.cs
  43. 2 8
      Rx.NET/Source/src/System.Reactive/Linq/Observable/GetEnumerator.cs
  44. 27 25
      Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupBy.cs
  45. 40 42
      Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupByUntil.cs
  46. 32 31
      Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupJoin.cs
  47. 2 5
      Rx.NET/Source/src/System.Reactive/Linq/Observable/If.cs
  48. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/IgnoreElements.cs
  49. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/IsEmpty.cs
  50. 29 30
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Join.cs
  51. 95 89
      Rx.NET/Source/src/System.Reactive/Linq/Observable/LastAsync.cs
  52. 122 0
      Rx.NET/Source/src/System.Reactive/Linq/Observable/LastOrDefaultAsync.cs
  53. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Latest.cs
  54. 83 75
      Rx.NET/Source/src/System.Reactive/Linq/Observable/LongCount.cs
  55. 2 5
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Materialize.cs
  56. 22 22
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs
  57. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/MaxBy.cs
  58. 259 254
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Merge.cs
  59. 22 22
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Min.cs
  60. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/MinBy.cs
  61. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/MostRecent.cs
  62. 8 11
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Multicast.cs
  63. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Next.cs
  64. 0 81
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ObserveOn.cs
  65. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/OfType.cs
  66. 1 1
      Rx.NET/Source/src/System.Reactive/Linq/Observable/OnErrorResumeNext.cs
  67. 4 10
      Rx.NET/Source/src/System.Reactive/Linq/Observable/PushToPullAdapter.cs
  68. 13 11
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Range.cs
  69. 12 15
      Rx.NET/Source/src/System.Reactive/Linq/Observable/RefCount.cs
  70. 100 78
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Repeat.cs
  71. 9 9
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Return.cs
  72. 18 28
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Sample.cs
  73. 13 19
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs
  74. 85 79
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs
  75. 668 735
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SelectMany.cs
  76. 228 221
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SequenceEqual.cs
  77. 101 95
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs
  78. 142 0
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs
  79. 111 109
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Skip.cs
  80. 95 89
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipLast.cs
  81. 21 26
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipUntil.cs
  82. 102 86
      Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipWhile.cs
  83. 10 10
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Sum.cs
  84. 12 13
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs
  85. 5 7
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Synchronize.cs
  86. 120 119
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Take.cs
  87. 164 153
      Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLast.cs
  88. 109 103
      Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLastBuffer.cs
  89. 23 31
      Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeUntil.cs
  90. 106 100
      Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeWhile.cs
  91. 21 19
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Throttle.cs
  92. 9 9
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Throw.cs
  93. 7 10
      Rx.NET/Source/src/System.Reactive/Linq/Observable/TimeInterval.cs
  94. 193 185
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Timeout.cs
  95. 231 184
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Timer.cs
  96. 6 6
      Rx.NET/Source/src/System.Reactive/Linq/Observable/Timestamp.cs
  97. 2 2
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ToArray.cs
  98. 8 6
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ToDictionary.cs
  99. 2 2
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ToList.cs
  100. 8 6
      Rx.NET/Source/src/System.Reactive/Linq/Observable/ToLookup.cs

+ 73 - 69
Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.ObserveOn.cs

@@ -7,34 +7,21 @@ using System.Threading;
 
 namespace System.Reactive.Concurrency
 {
-    internal sealed class ObserveOn<TSource> : Producer<TSource>
+    internal static class ObserveOn<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly IScheduler _scheduler;
-        private readonly SynchronizationContext _context;
-
-        public ObserveOn(IObservable<TSource> source, IScheduler scheduler)
-        {
-            _source = source;
-            _scheduler = scheduler;
-        }
-
-        public ObserveOn(IObservable<TSource> source, SynchronizationContext context)
+        internal sealed class Scheduler : Producer<TSource>
         {
-            _source = source;
-            _context = context;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly IScheduler _scheduler;
 
-        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")]
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_context != null)
+            public Scheduler(IObservable<TSource> source, IScheduler scheduler)
             {
-                var sink = new ObserveOnSink(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _source = source;
+                _scheduler = scheduler;
             }
-            else
+
+            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")]
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
                 var sink = new ObserveOnObserver<TSource>(_scheduler, observer, cancel);
                 setSink(sink);
@@ -42,66 +29,83 @@ namespace System.Reactive.Concurrency
             }
         }
 
-        private sealed class ObserveOnSink : Sink<TSource>, IObserver<TSource>
+        internal sealed class Context : Producer<TSource>
         {
-            private readonly ObserveOn<TSource> _parent;
+            private readonly IObservable<TSource> _source;
+            private readonly SynchronizationContext _context;
 
-            public ObserveOnSink(ObserveOn<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Context(IObservable<TSource> source, SynchronizationContext context)
             {
-                _parent = parent;
+                _source = source;
+                _context = context;
             }
 
-            public IDisposable Run()
+            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")]
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                //
-                // The interactions with OperationStarted/OperationCompleted below allow
-                // for test frameworks to wait until a whole sequence is observed, running
-                // asserts on a per-message level. Also, for ASP.NET pages, the use of the
-                // built-in synchronization context would allow processing to finished in
-                // its entirety before moving on with the page lifecycle.
-                //
-                _parent._context.OperationStarted();
-
-                var d = _parent._source.SubscribeSafe(this);
-                var c = Disposable.Create(() =>
-                {
-                    _parent._context.OperationCompleted();
-                });
-
-                return StableCompositeDisposable.Create(d, c);
+                var sink = new _(_context, observer, cancel);
+                setSink(sink);
+                return sink.Run(_source);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _parent._context.Post(OnNextPosted, value);
-            }
+                private readonly SynchronizationContext _context;
 
-            public void OnError(Exception error)
-            {
-                _parent._context.Post(OnErrorPosted, error);
-            }
+                public _(SynchronizationContext context, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _context = context;
+                }
 
-            public void OnCompleted()
-            {
-                _parent._context.Post(OnCompletedPosted, state: null);
-            }
+                public IDisposable Run(IObservable<TSource> source)
+                {
+                    //
+                    // The interactions with OperationStarted/OperationCompleted below allow
+                    // for test frameworks to wait until a whole sequence is observed, running
+                    // asserts on a per-message level. Also, for ASP.NET pages, the use of the
+                    // built-in synchronization context would allow processing to finished in
+                    // its entirety before moving on with the page lifecycle.
+                    //
+                    _context.OperationStarted();
+
+                    var d = source.SubscribeSafe(this);
+                    var c = Disposable.Create(_context.OperationCompleted);
+
+                    return StableCompositeDisposable.Create(d, c);
+                }
+
+                public void OnNext(TSource value)
+                {
+                    _context.Post(OnNextPosted, value);
+                }
 
-            private void OnNextPosted(object value)
-            {
-                _observer.OnNext((TSource)value);
-            }
+                public void OnError(Exception error)
+                {
+                    _context.Post(OnErrorPosted, error);
+                }
 
-            private void OnErrorPosted(object error)
-            {
-                _observer.OnError((Exception)error);
-                Dispose();
-            }
+                public void OnCompleted()
+                {
+                    _context.Post(OnCompletedPosted, state: null);
+                }
 
-            private void OnCompletedPosted(object ignored)
-            {
-                _observer.OnCompleted();
-                Dispose();
+                private void OnNextPosted(object value)
+                {
+                    _observer.OnNext((TSource)value);
+                }
+
+                private void OnErrorPosted(object error)
+                {
+                    _observer.OnError((Exception)error);
+                    Dispose();
+                }
+
+                private void OnCompletedPosted(object ignored)
+                {
+                    _observer.OnCompleted();
+                    Dispose();
+                }
             }
         }
     }

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

@@ -102,7 +102,7 @@ namespace System.Reactive.Concurrency
             if (scheduler == null)
                 throw new ArgumentNullException(nameof(scheduler));
 
-            return new ObserveOn<TSource>(source, scheduler);
+            return new ObserveOn<TSource>.Scheduler(source, scheduler);
         }
 
         /// <summary>
@@ -120,7 +120,7 @@ namespace System.Reactive.Concurrency
             if (context == null)
                 throw new ArgumentNullException(nameof(context));
 
-            return new ObserveOn<TSource>(source, context);
+            return new ObserveOn<TSource>.Context(source, context);
         }
 
         #endregion

+ 29 - 0
Rx.NET/Source/src/System.Reactive/Internal/Helpers.cs

@@ -39,5 +39,34 @@ namespace System.Reactive
 
             return source;
         }
+
+        public static bool All(this bool[] values)
+        {
+            foreach (var value in values)
+            {
+                if (!value)
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        public static bool AllExcept(this bool[] values, int index)
+        {
+            for (var i = 0; i < values.Length; i++)
+            {
+                if (i != index)
+                {
+                    if (!values[i])
+                    {
+                        return false;
+                    }
+                }
+            }
+
+            return true;
+        }
     }
 }

+ 4 - 8
Rx.NET/Source/src/System.Reactive/Linq/GroupedObservable.cs

@@ -7,29 +7,25 @@ using System.Reactive.Subjects;
 
 namespace System.Reactive.Linq
 {
-    class GroupedObservable<TKey, TElement> : ObservableBase<TElement>, IGroupedObservable<TKey, TElement>
+    internal sealed class GroupedObservable<TKey, TElement> : ObservableBase<TElement>, IGroupedObservable<TKey, TElement>
     {
-        private readonly TKey _key;
         private readonly IObservable<TElement> _subject;
         private readonly RefCountDisposable _refCount;
 
         public GroupedObservable(TKey key, ISubject<TElement> subject, RefCountDisposable refCount)
         {
-            _key = key;
+            Key = key;
             _subject = subject;
             _refCount = refCount;
         }
 
         public GroupedObservable(TKey key, ISubject<TElement> subject)
         {
-            _key = key;
+            Key = key;
             _subject = subject;
         }
 
-        public TKey Key
-        {
-            get { return _key; }
-        }
+        public TKey Key { get; }
 
         protected override IDisposable SubscribeCore(IObserver<TElement> observer)
         {

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/AddRef.cs

@@ -26,7 +26,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 119 - 55
Rx.NET/Source/src/System.Reactive/Linq/Observable/Aggregate.cs

@@ -4,50 +4,56 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Aggregate<TSource, TAccumulate, TResult> : Producer<TResult>
+    internal sealed class Aggregate<TSource> : Producer<TSource>
     {
         private readonly IObservable<TSource> _source;
-        private readonly TAccumulate _seed;
-        private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
-        private readonly Func<TAccumulate, TResult> _resultSelector;
+        private readonly Func<TSource, TSource, TSource> _accumulator;
 
-        public Aggregate(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)
+        public Aggregate(IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
         {
             _source = source;
-            _seed = seed;
             _accumulator = accumulator;
-            _resultSelector = resultSelector;
         }
 
-        protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_accumulator, observer, cancel);
             setSink(sink);
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TResult>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Aggregate<TSource, TAccumulate, TResult> _parent;
-            private TAccumulate _accumulation;
+            private readonly Func<TSource, TSource, TSource> _accumulator;
+            private TSource _accumulation;
+            private bool _hasAccumulation;
 
-            public _(Aggregate<TSource, TAccumulate, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<TSource, TSource, TSource> accumulator, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _accumulation = _parent._seed;
+                _accumulator = accumulator;
+                _accumulation = default(TSource);
+                _hasAccumulation = false;
             }
 
             public void OnNext(TSource value)
             {
-                try
+                if (!_hasAccumulation)
                 {
-                    _accumulation = _parent._accumulator(_accumulation, value);
+                    _accumulation = value;
+                    _hasAccumulation = true;
                 }
-                catch (Exception exception)
+                else
                 {
-                    base._observer.OnError(exception);
-                    base.Dispose();
+                    try
+                    {
+                        _accumulation = _accumulator(_accumulation, value);
+                    }
+                    catch (Exception exception)
+                    {
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                    }
                 }
             }
 
@@ -59,75 +65,129 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void OnCompleted()
             {
-                var result = default(TResult);
+                if (!_hasAccumulation)
+                {
+                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+                    base.Dispose();
+                }
+                else
+                {
+                    base._observer.OnNext(_accumulation);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+    }
+
+    internal sealed class Aggregate<TSource, TAccumulate> : Producer<TAccumulate>
+    {
+        private readonly IObservable<TSource> _source;
+        private readonly TAccumulate _seed;
+        private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
+
+        public Aggregate(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
+        {
+            _source = source;
+            _seed = seed;
+            _accumulator = accumulator;
+        }
+
+        protected override IDisposable Run(IObserver<TAccumulate> observer, IDisposable cancel, Action<IDisposable> setSink)
+        {
+            var sink = new _(_seed, _accumulator, observer, cancel);
+            setSink(sink);
+            return _source.SubscribeSafe(sink);
+        }
+
+        private sealed class _ : Sink<TAccumulate>, IObserver<TSource>
+        {
+            private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
+            private TAccumulate _accumulation;
+
+            public _(TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, IObserver<TAccumulate> observer, IDisposable cancel)
+                : base(observer, cancel)
+            {
+                _accumulator = accumulator;
+                _accumulation = seed;
+            }
+
+            public void OnNext(TSource value)
+            {
                 try
                 {
-                    result = _parent._resultSelector(_accumulation);
+                    _accumulation = _accumulator(_accumulation, value);
                 }
                 catch (Exception exception)
                 {
                     base._observer.OnError(exception);
                     base.Dispose();
-                    return;
                 }
+            }
 
-                base._observer.OnNext(result);
+            public void OnError(Exception error)
+            {
+                base._observer.OnError(error);
+                base.Dispose();
+            }
+
+            public void OnCompleted()
+            {
+                base._observer.OnNext(_accumulation);
                 base._observer.OnCompleted();
                 base.Dispose();
             }
         }
     }
 
-    internal sealed class Aggregate<TSource> : Producer<TSource>
+    internal sealed class Aggregate<TSource, TAccumulate, TResult> : Producer<TResult>
     {
         private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, TSource, TSource> _accumulator;
+        private readonly TAccumulate _seed;
+        private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
+        private readonly Func<TAccumulate, TResult> _resultSelector;
 
-        public Aggregate(IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
+        public Aggregate(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)
         {
             _source = source;
+            _seed = seed;
             _accumulator = accumulator;
+            _resultSelector = resultSelector;
         }
 
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+        protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
             var sink = new _(this, observer, cancel);
             setSink(sink);
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TResult>, IObserver<TSource>
         {
-            private readonly Aggregate<TSource> _parent;
-            private TSource _accumulation;
-            private bool _hasAccumulation;
+            private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
+            private readonly Func<TAccumulate, TResult> _resultSelector;
+
+            private TAccumulate _accumulation;
 
-            public _(Aggregate<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(Aggregate<TSource, TAccumulate, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _accumulation = default(TSource);
-                _hasAccumulation = false;
+                _accumulator = parent._accumulator;
+                _resultSelector = parent._resultSelector;
+
+                _accumulation = parent._seed;
             }
 
             public void OnNext(TSource value)
             {
-                if (!_hasAccumulation)
+                try
                 {
-                    _accumulation = value;
-                    _hasAccumulation = true;
+                    _accumulation = _accumulator(_accumulation, value);
                 }
-                else
+                catch (Exception exception)
                 {
-                    try
-                    {
-                        _accumulation = _parent._accumulator(_accumulation, value);
-                    }
-                    catch (Exception exception)
-                    {
-                        base._observer.OnError(exception);
-                        base.Dispose();
-                    }
+                    base._observer.OnError(exception);
+                    base.Dispose();
                 }
             }
 
@@ -139,17 +199,21 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void OnCompleted()
             {
-                if (!_hasAccumulation)
+                var result = default(TResult);
+                try
                 {
-                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
-                    base.Dispose();
+                    result = _resultSelector(_accumulation);
                 }
-                else
+                catch (Exception exception)
                 {
-                    base._observer.OnNext(_accumulation);
-                    base._observer.OnCompleted();
+                    base._observer.OnError(exception);
                     base.Dispose();
+                    return;
                 }
+
+                base._observer.OnNext(result);
+                base._observer.OnCompleted();
+                base.Dispose();
             }
         }
     }

+ 6 - 6
Rx.NET/Source/src/System.Reactive/Linq/Observable/All.cs

@@ -17,19 +17,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_predicate, observer, cancel);
             setSink(sink);
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<bool>, IObserver<TSource>
+        private sealed class _ : Sink<bool>, IObserver<TSource>
         {
-            private readonly All<TSource> _parent;
+            private readonly Func<TSource, bool> _predicate;
 
-            public _(All<TSource> parent, IObserver<bool> observer, IDisposable cancel)
+            public _(Func<TSource, bool> predicate, IObserver<bool> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _predicate = predicate;
             }
 
             public void OnNext(TSource value)
@@ -37,7 +37,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 var res = false;
                 try
                 {
-                    res = _parent._predicate(value);
+                    res = _predicate(value);
                 }
                 catch (Exception ex)
                 {

+ 13 - 14
Rx.NET/Source/src/System.Reactive/Linq/Observable/Amb.cs

@@ -19,24 +19,21 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _( observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>
+        private sealed class _ : Sink<TSource>
         {
-            private readonly Amb<TSource> _parent;
-
-            public _(Amb<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
             private AmbState _choice;
 
-            public IDisposable Run()
+            public IDisposable Run(Amb<TSource> parent)
             {
                 var ls = new SingleAssignmentDisposable();
                 var rs = new SingleAssignmentDisposable();
@@ -54,13 +51,13 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 _choice = AmbState.Neither;
 
-                ls.Disposable = _parent._left.SubscribeSafe(lo);
-                rs.Disposable = _parent._right.SubscribeSafe(ro);
+                ls.Disposable = parent._left.SubscribeSafe(lo);
+                rs.Disposable = parent._right.SubscribeSafe(ro);
 
                 return d;
             }
 
-            class DecisionObserver : IObserver<TSource>
+            private sealed class DecisionObserver : IObserver<TSource>
             {
                 private readonly _ _parent;
                 private readonly AmbState _me;
@@ -92,7 +89,9 @@ namespace System.Reactive.Linq.ObservableImpl
                         }
 
                         if (_parent._choice == _me)
+                        {
                             _parent._observer.OnNext(value);
+                        }
                     }
                 }
 
@@ -137,7 +136,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class AmbObserver : IObserver<TSource>
+            private sealed class AmbObserver : IObserver<TSource>
             {
                 public IObserver<TSource> _target;
 
@@ -161,11 +160,11 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            enum AmbState
+            private enum AmbState
             {
                 Left,
                 Right,
-                Neither
+                Neither,
             }
         }
     }

+ 75 - 69
Rx.NET/Source/src/System.Reactive/Linq/Observable/Any.cs

@@ -4,110 +4,116 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Any<TSource> : Producer<bool>
+    internal static class Any<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-
-        public Any(IObservable<TSource> source)
+        internal sealed class Count : Producer<bool>
         {
-            _source = source;
-        }
+            private readonly IObservable<TSource> _source;
 
-        public Any(IObservable<TSource> source, Func<TSource, bool> predicate)
-        {
-            _source = source;
-            _predicate = predicate;
-        }
-
-        protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate != null)
+            public Count(IObservable<TSource> source)
             {
-                var sink = new AnyImpl(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
             }
-            else
+
+            protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
                 var sink = new _(observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
 
-        class _ : Sink<bool>, IObserver<TSource>
-        {
-            public _(IObserver<bool> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<bool>, IObserver<TSource>
             {
-            }
+                public _(IObserver<bool> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                }
 
-            public void OnNext(TSource value)
-            {
-                base._observer.OnNext(true);
-                base._observer.OnCompleted();
-                base.Dispose();
-            }
+                public void OnNext(TSource value)
+                {
+                    base._observer.OnNext(true);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
 
-            public void OnCompleted()
-            {
-                base._observer.OnNext(false);
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(false);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class AnyImpl : Sink<bool>, IObserver<TSource>
+        internal sealed class Predicate : Producer<bool>
         {
-            private readonly Any<TSource> _parent;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
 
-            public AnyImpl(Any<TSource> parent, IObserver<bool> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
             {
-                _parent = parent;
+                _source = source;
+                _predicate = predicate;
             }
 
-            public void OnNext(TSource value)
+            protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var res = false;
-                try
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<bool>, IObserver<TSource>
+            {
+                private readonly Func<TSource, bool> _predicate;
+
+                public _(Func<TSource, bool> predicate, IObserver<bool> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    res = _parent._predicate(value);
+                    _predicate = predicate;
                 }
-                catch (Exception ex)
+
+                public void OnNext(TSource value)
+                {
+                    var res = false;
+                    try
+                    {
+                        res = _predicate(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    if (res)
+                    {
+                        base._observer.OnNext(true);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
+                }
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(ex);
+                    base._observer.OnError(error);
                     base.Dispose();
-                    return;
                 }
 
-                if (res)
+                public void OnCompleted()
                 {
-                    base._observer.OnNext(true);
+                    base._observer.OnNext(false);
                     base._observer.OnCompleted();
                     base.Dispose();
                 }
             }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
-
-            public void OnCompleted()
-            {
-                base._observer.OnNext(false);
-                base._observer.OnCompleted();
-                base.Dispose();
-            }
         }
     }
 }

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

@@ -13,10 +13,7 @@ namespace System.Reactive.Linq.ObservableImpl
             _source = source;
         }
 
-        public IObservable<TSource> Eval()
-        {
-            return _source;
-        }
+        public IObservable<TSource> Eval() => _source;
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
@@ -25,7 +22,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 10 - 10
Rx.NET/Source/src/System.Reactive/Linq/Observable/Average.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double>, IObserver<double>
+        private sealed class _ : Sink<double>, IObserver<double>
         {
             private double _sum;
             private long _count;
@@ -88,7 +88,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float>, IObserver<float>
+        private sealed class _ : Sink<float>, IObserver<float>
         {
             private double _sum; // NOTE: Uses a different accumulator type (double), conform LINQ to Objects.
             private long _count;
@@ -156,7 +156,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal>, IObserver<decimal>
+        private sealed class _ : Sink<decimal>, IObserver<decimal>
         {
             private decimal _sum;
             private long _count;
@@ -224,7 +224,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double>, IObserver<int>
+        private sealed class _ : Sink<double>, IObserver<int>
         {
             private long _sum;
             private long _count;
@@ -292,7 +292,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double>, IObserver<long>
+        private sealed class _ : Sink<double>, IObserver<long>
         {
             private long _sum;
             private long _count;
@@ -360,7 +360,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double?>, IObserver<double?>
+        private sealed class _ : Sink<double?>, IObserver<double?>
         {
             private double _sum;
             private long _count;
@@ -431,7 +431,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float?>, IObserver<float?>
+        private sealed class _ : Sink<float?>, IObserver<float?>
         {
             private double _sum; // NOTE: Uses a different accumulator type (double), conform LINQ to Objects.
             private long _count;
@@ -502,7 +502,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal?>, IObserver<decimal?>
+        private sealed class _ : Sink<decimal?>, IObserver<decimal?>
         {
             private decimal _sum;
             private long _count;
@@ -573,7 +573,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double?>, IObserver<int?>
+        private sealed class _ : Sink<double?>, IObserver<int?>
         {
             private long _sum;
             private long _count;
@@ -644,7 +644,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double?>, IObserver<long?>
+        private sealed class _ : Sink<double?>, IObserver<long?>
         {
             private long _sum;
             private long _count;

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

@@ -8,697 +8,709 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Buffer<TSource> : Producer<IList<TSource>>
+    internal static class Buffer<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly int _count;
-        private readonly int _skip;
-
-        private readonly TimeSpan _timeSpan;
-        private readonly TimeSpan _timeShift;
-        private readonly IScheduler _scheduler;
-
-        public Buffer(IObservable<TSource> source, int count, int skip)
-        {
-            _source = source;
-            _count = count;
-            _skip = skip;
-        }
-
-        public Buffer(IObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler)
+        internal sealed class Count : Producer<IList<TSource>>
         {
-            _source = source;
-            _timeSpan = timeSpan;
-            _timeShift = timeShift;
-            _scheduler = scheduler;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly int _count;
+            private readonly int _skip;
 
-        public Buffer(IObservable<TSource> source, TimeSpan timeSpan, int count, IScheduler scheduler)
-        {
-            _source = source;
-            _timeSpan = timeSpan;
-            _count = count;
-            _scheduler = scheduler;
-        }
-
-        protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_scheduler == null)
+            public Count(IObservable<TSource> source, int count, int skip)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _source = source;
+                _count = count;
+                _skip = skip;
             }
-            else if (_count > 0)
+
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new Impl(this, observer, cancel);
+                var sink = new _(this, observer, cancel);
                 setSink(sink);
-                return sink.Run();
-            }
-            else
-            {
-                if (_timeSpan == _timeShift)
-                {
-                    var sink = new BufferTimeShift(this, observer, cancel);
-                    setSink(sink);
-                    return sink.Run();
-                }
-                else
-                {
-                    var sink = new BufferImpl(this, observer, cancel);
-                    setSink(sink);
-                    return sink.Run();
-                }
+                return sink.Run(_source);
             }
-        }
-
-        class _ : Sink<IList<TSource>>, IObserver<TSource>
-        {
-            private readonly Buffer<TSource> _parent;
 
-            public _(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                _parent = parent;
-            }
+                private readonly Queue<IList<TSource>> _queue = new Queue<IList<TSource>>();
 
-            private Queue<IList<TSource>> _queue;
-            private int _n;
+                private readonly int _count;
+                private readonly int _skip;
 
-            public IDisposable Run()
-            {
-                _queue = new Queue<IList<TSource>>();
-                _n = 0;
+                public _(Count parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _count = parent._count;
+                    _skip = parent._skip;
+                }
 
-                CreateWindow();
-                return _parent._source.SubscribeSafe(this);
-            }
+                private int _n;
 
-            private void CreateWindow()
-            {
-                var s = new List<TSource>();
-                _queue.Enqueue(s);
-            }
+                public IDisposable Run(IObservable<TSource> source)
+                {
+                    _n = 0;
 
-            public void OnNext(TSource value)
-            {
-                foreach (var s in _queue)
-                    s.Add(value);
+                    CreateWindow();
+                    return source.SubscribeSafe(this);
+                }
 
-                var c = _n - _parent._count + 1;
-                if (c >= 0 && c % _parent._skip == 0)
+                private void CreateWindow()
                 {
-                    var s = _queue.Dequeue();
-                    if (s.Count > 0)
-                        base._observer.OnNext(s);
+                    var s = new List<TSource>();
+                    _queue.Enqueue(s);
                 }
 
-                _n++;
-                if (_n % _parent._skip == 0)
-                    CreateWindow();
-            }
+                public void OnNext(TSource value)
+                {
+                    foreach (var s in _queue)
+                        s.Add(value);
 
-            public void OnError(Exception error)
-            {
-                while (_queue.Count > 0)
-                    _queue.Dequeue().Clear();
+                    var c = _n - _count + 1;
+                    if (c >= 0 && c % _skip == 0)
+                    {
+                        var s = _queue.Dequeue();
+                        if (s.Count > 0)
+                            base._observer.OnNext(s);
+                    }
 
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                    _n++;
+                    if (_n % _skip == 0)
+                        CreateWindow();
+                }
 
-            public void OnCompleted()
-            {
-                while (_queue.Count > 0)
+                public void OnError(Exception error)
                 {
-                    var s = _queue.Dequeue();
-                    if (s.Count > 0)
-                        base._observer.OnNext(s);
+                    while (_queue.Count > 0)
+                        _queue.Dequeue().Clear();
+
+                    base._observer.OnError(error);
+                    base.Dispose();
                 }
 
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    while (_queue.Count > 0)
+                    {
+                        var s = _queue.Dequeue();
+                        if (s.Count > 0)
+                            base._observer.OnNext(s);
+                    }
+
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class BufferImpl : Sink<IList<TSource>>, IObserver<TSource>
+        internal sealed class TimeSliding : Producer<IList<TSource>>
         {
-            private readonly Buffer<TSource> _parent;
+            private readonly IObservable<TSource> _source;
+
+            private readonly TimeSpan _timeSpan;
+            private readonly TimeSpan _timeShift;
+            private readonly IScheduler _scheduler;
 
-            public BufferImpl(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public TimeSliding(IObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler)
             {
-                _parent = parent;
+                _source = source;
+                _timeSpan = timeSpan;
+                _timeShift = timeShift;
+                _scheduler = scheduler;
             }
 
-            private TimeSpan _totalTime;
-            private TimeSpan _nextShift;
-            private TimeSpan _nextSpan;
-
-            private object _gate;
-            private Queue<List<TSource>> _q;
-
-            private SerialDisposable _timerD;
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(this, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
+            }
 
-            public IDisposable Run()
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                _totalTime = TimeSpan.Zero;
-                _nextShift = _parent._timeShift;
-                _nextSpan = _parent._timeSpan;
+                private readonly TimeSpan _timeShift;
+                private readonly IScheduler _scheduler;
 
-                _gate = new object();
-                _q = new Queue<List<TSource>>();
+                private readonly object _gate = new object();
+                private readonly Queue<List<TSource>> _q = new Queue<List<TSource>>();
+                private readonly SerialDisposable _timerD = new SerialDisposable();
 
-                _timerD = new SerialDisposable();
+                public _(TimeSliding parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _timeShift = parent._timeShift;
+                    _scheduler = parent._scheduler;
+                }
 
-                CreateWindow();
-                CreateTimer();
+                private TimeSpan _totalTime;
+                private TimeSpan _nextShift;
+                private TimeSpan _nextSpan;
 
-                var subscription = _parent._source.SubscribeSafe(this);
+                public IDisposable Run(TimeSliding parent)
+                {
+                    _totalTime = TimeSpan.Zero;
+                    _nextShift = parent._timeShift;
+                    _nextSpan = parent._timeSpan;
 
-                return StableCompositeDisposable.Create(_timerD, subscription);
-            }
+                    CreateWindow();
+                    CreateTimer();
 
-            private void CreateWindow()
-            {
-                var s = new List<TSource>();
-                _q.Enqueue(s);
-            }
+                    var subscription = parent._source.SubscribeSafe(this);
 
-            private void CreateTimer()
-            {
-                var m = new SingleAssignmentDisposable();
-                _timerD.Disposable = m;
+                    return StableCompositeDisposable.Create(_timerD, subscription);
+                }
 
-                var isSpan = false;
-                var isShift = false;
-                if (_nextSpan == _nextShift)
+                private void CreateWindow()
                 {
-                    isSpan = true;
-                    isShift = true;
+                    var s = new List<TSource>();
+                    _q.Enqueue(s);
                 }
-                else if (_nextSpan < _nextShift)
-                    isSpan = true;
-                else
-                    isShift = true;
 
-                var newTotalTime = isSpan ? _nextSpan : _nextShift;
-                var ts = newTotalTime - _totalTime;
-                _totalTime = newTotalTime;
+                private void CreateTimer()
+                {
+                    var m = new SingleAssignmentDisposable();
+                    _timerD.Disposable = m;
 
-                if (isSpan)
-                    _nextSpan += _parent._timeShift;
-                if (isShift)
-                    _nextShift += _parent._timeShift;
+                    var isSpan = false;
+                    var isShift = false;
+                    if (_nextSpan == _nextShift)
+                    {
+                        isSpan = true;
+                        isShift = true;
+                    }
+                    else if (_nextSpan < _nextShift)
+                        isSpan = true;
+                    else
+                        isShift = true;
 
-                m.Disposable = _parent._scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick);
-            }
+                    var newTotalTime = isSpan ? _nextSpan : _nextShift;
+                    var ts = newTotalTime - _totalTime;
+                    _totalTime = newTotalTime;
 
-            struct State
-            {
-                public bool isSpan;
-                public bool isShift;
-            }
+                    if (isSpan)
+                        _nextSpan += _timeShift;
+                    if (isShift)
+                        _nextShift += _timeShift;
 
-            private IDisposable Tick(IScheduler self, State state)
-            {
-                lock (_gate)
+                    m.Disposable = _scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick);
+                }
+
+                private struct State
                 {
-                    //
-                    // Before v2, the two operations below were reversed. This doesn't have an observable
-                    // difference for Buffer, but is done to keep code consistent with Window, where we
-                    // took a breaking change in v2 to ensure consistency across overloads. For more info,
-                    // see the comment in Tick for Window.
-                    //
-                    if (state.isSpan)
-                    {
-                        var s = _q.Dequeue();
-                        base._observer.OnNext(s);
-                    }
+                    public bool isSpan;
+                    public bool isShift;
+                }
 
-                    if (state.isShift)
+                private IDisposable Tick(IScheduler self, State state)
+                {
+                    lock (_gate)
                     {
-                        CreateWindow();
+                        //
+                        // Before v2, the two operations below were reversed. This doesn't have an observable
+                        // difference for Buffer, but is done to keep code consistent with Window, where we
+                        // took a breaking change in v2 to ensure consistency across overloads. For more info,
+                        // see the comment in Tick for Window.
+                        //
+                        if (state.isSpan)
+                        {
+                            var s = _q.Dequeue();
+                            base._observer.OnNext(s);
+                        }
+
+                        if (state.isShift)
+                        {
+                            CreateWindow();
+                        }
                     }
-                }
 
-                CreateTimer();
+                    CreateTimer();
 
-                return Disposable.Empty;
-            }
+                    return Disposable.Empty;
+                }
 
-            public void OnNext(TSource value)
-            {
-                lock (_gate)
+                public void OnNext(TSource value)
                 {
-                    foreach (var s in _q)
-                        s.Add(value);
+                    lock (_gate)
+                    {
+                        foreach (var s in _q)
+                            s.Add(value);
+                    }
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                lock (_gate)
+                public void OnError(Exception error)
                 {
-                    while (_q.Count > 0)
-                        _q.Dequeue().Clear();
+                    lock (_gate)
+                    {
+                        while (_q.Count > 0)
+                            _q.Dequeue().Clear();
 
-                    base._observer.OnError(error);
-                    base.Dispose();
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
-            }
 
-            public void OnCompleted()
-            {
-                lock (_gate)
+                public void OnCompleted()
                 {
-                    while (_q.Count > 0)
-                        base._observer.OnNext(_q.Dequeue());
+                    lock (_gate)
+                    {
+                        while (_q.Count > 0)
+                            base._observer.OnNext(_q.Dequeue());
 
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
             }
         }
 
-        class BufferTimeShift : Sink<IList<TSource>>, IObserver<TSource>
+        internal sealed class TimeHopping : Producer<IList<TSource>>
         {
-            private readonly Buffer<TSource> _parent;
+            private readonly IObservable<TSource> _source;
 
-            public BufferTimeShift(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private readonly TimeSpan _timeSpan;
+            private readonly IScheduler _scheduler;
+
+            public TimeHopping(IObservable<TSource> source, TimeSpan timeSpan, IScheduler scheduler)
             {
-                _parent = parent;
+                _source = source;
+                _timeSpan = timeSpan;
+                _scheduler = scheduler;
             }
 
-            private object _gate;
-            private List<TSource> _list;
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _( observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
+            }
 
-            public IDisposable Run()
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                _gate = new object();
-                _list = new List<TSource>();
+                private readonly object _gate = new object();
 
-                var d = _parent._scheduler.SchedulePeriodic(_parent._timeSpan, Tick);
-                var s = _parent._source.SubscribeSafe(this);
+                public _(IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                }
 
-                return StableCompositeDisposable.Create(d, s);
-            }
+                private List<TSource> _list;
 
-            private void Tick()
-            {
-                lock (_gate)
+                public IDisposable Run(TimeHopping parent)
                 {
-                    base._observer.OnNext(_list);
                     _list = new List<TSource>();
+
+                    var d = parent._scheduler.SchedulePeriodic(parent._timeSpan, Tick);
+                    var s = parent._source.SubscribeSafe(this);
+
+                    return StableCompositeDisposable.Create(d, s);
                 }
-            }
 
-            public void OnNext(TSource value)
-            {
-                lock (_gate)
+                private void Tick()
                 {
-                    _list.Add(value);
+                    lock (_gate)
+                    {
+                        base._observer.OnNext(_list);
+                        _list = new List<TSource>();
+                    }
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                lock (_gate)
+                public void OnNext(TSource value)
                 {
-                    _list.Clear();
+                    lock (_gate)
+                    {
+                        _list.Add(value);
+                    }
+                }
 
-                    base._observer.OnError(error);
-                    base.Dispose();
+                public void OnError(Exception error)
+                {
+                    lock (_gate)
+                    {
+                        _list.Clear();
+
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
-            }
 
-            public void OnCompleted()
-            {
-                lock (_gate)
+                public void OnCompleted()
                 {
-                    base._observer.OnNext(_list);
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        base._observer.OnNext(_list);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
             }
         }
 
-        class Impl : Sink<IList<TSource>>, IObserver<TSource>
+        internal sealed class Ferry : Producer<IList<TSource>>
         {
-            private readonly Buffer<TSource> _parent;
+            private readonly IObservable<TSource> _source;
+            private readonly int _count;
+            private readonly TimeSpan _timeSpan;
+            private readonly IScheduler _scheduler;
 
-            public Impl(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Ferry(IObservable<TSource> source, TimeSpan timeSpan, int count, IScheduler scheduler)
             {
-                _parent = parent;
+                _source = source;
+                _timeSpan = timeSpan;
+                _count = count;
+                _scheduler = scheduler;
             }
 
-            private object _gate;
-            private IList<TSource> _s;
-            private int _n;
-            private int _windowId;
-
-            private SerialDisposable _timerD;
-
-            public IDisposable Run()
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _gate = new object();
-                _s = default(IList<TSource>);
-                _n = 0;
-                _windowId = 0;
-
-                _timerD = new SerialDisposable();
-
-                _s = new List<TSource>();
-                CreateTimer(0);
-
-                var subscription = _parent._source.SubscribeSafe(this);
-
-                return StableCompositeDisposable.Create(_timerD, subscription);
+                var sink = new _(this, observer, cancel);
+                setSink(sink);
+                return sink.Run();
             }
 
-            private void CreateTimer(int id)
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                var m = new SingleAssignmentDisposable();
-                _timerD.Disposable = m;
+                private readonly Ferry _parent;
 
-                m.Disposable = _parent._scheduler.Schedule(id, _parent._timeSpan, Tick);
-            }
+                private readonly object _gate = new object();
+                private readonly SerialDisposable _timerD = new SerialDisposable();
 
-            private IDisposable Tick(IScheduler self, int id)
-            {
-                var d = Disposable.Empty;
-
-                var newId = 0;
-                lock (_gate)
+                public _(Ferry parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    if (id != _windowId)
-                        return d;
+                    _parent = parent;
+                }
 
-                    _n = 0;
-                    newId = ++_windowId;
+                private IList<TSource> _s;
+                private int _n;
+                private int _windowId;
 
-                    var res = _s;
+                public IDisposable Run()
+                {
                     _s = new List<TSource>();
-                    base._observer.OnNext(res);
+                    _n = 0;
+                    _windowId = 0;
+
+                    CreateTimer(0);
+
+                    var subscription = _parent._source.SubscribeSafe(this);
 
-                    CreateTimer(newId);
+                    return StableCompositeDisposable.Create(_timerD, subscription);
                 }
 
-                return d;
-            }
+                private void CreateTimer(int id)
+                {
+                    var m = new SingleAssignmentDisposable();
+                    _timerD.Disposable = m;
 
-            public void OnNext(TSource value)
-            {
-                var newWindow = false;
-                var newId = 0;
+                    m.Disposable = _parent._scheduler.Schedule(id, _parent._timeSpan, Tick);
+                }
 
-                lock (_gate)
+                private IDisposable Tick(IScheduler self, int id)
                 {
-                    _s.Add(value);
+                    var d = Disposable.Empty;
 
-                    _n++;
-                    if (_n == _parent._count)
+                    var newId = 0;
+                    lock (_gate)
                     {
-                        newWindow = true;
+                        if (id != _windowId)
+                            return d;
+
                         _n = 0;
                         newId = ++_windowId;
 
                         var res = _s;
                         _s = new List<TSource>();
                         base._observer.OnNext(res);
-                    }
 
-                    if (newWindow)
                         CreateTimer(newId);
+                    }
+
+                    return d;
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                lock (_gate)
+                public void OnNext(TSource value)
                 {
-                    _s.Clear();
-                    base._observer.OnError(error);
-                    base.Dispose();
+                    var newWindow = false;
+                    var newId = 0;
+
+                    lock (_gate)
+                    {
+                        _s.Add(value);
+
+                        _n++;
+                        if (_n == _parent._count)
+                        {
+                            newWindow = true;
+                            _n = 0;
+                            newId = ++_windowId;
+
+                            var res = _s;
+                            _s = new List<TSource>();
+                            base._observer.OnNext(res);
+                        }
+
+                        if (newWindow)
+                            CreateTimer(newId);
+                    }
                 }
-            }
 
-            public void OnCompleted()
-            {
-                lock (_gate)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnNext(_s);
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        _s.Clear();
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
+                }
+
+                public void OnCompleted()
+                {
+                    lock (_gate)
+                    {
+                        base._observer.OnNext(_s);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
             }
         }
     }
 
-    internal sealed class Buffer<TSource, TBufferClosing> : Producer<IList<TSource>>
+    internal static class Buffer<TSource, TBufferClosing>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<IObservable<TBufferClosing>> _bufferClosingSelector;
-        private readonly IObservable<TBufferClosing> _bufferBoundaries;
-
-        public Buffer(IObservable<TSource> source, Func<IObservable<TBufferClosing>> bufferClosingSelector)
+        internal sealed class Selector : Producer<IList<TSource>>
         {
-            _source = source;
-            _bufferClosingSelector = bufferClosingSelector;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly Func<IObservable<TBufferClosing>> _bufferClosingSelector;
 
-        public Buffer(IObservable<TSource> source, IObservable<TBufferClosing> bufferBoundaries)
-        {
-            _source = source;
-            _bufferBoundaries = bufferBoundaries;
-        }
-
-        protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_bufferClosingSelector != null)
+            public Selector(IObservable<TSource> source, Func<IObservable<TBufferClosing>> bufferClosingSelector)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _source = source;
+                _bufferClosingSelector = bufferClosingSelector;
             }
-            else
+
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new Beta(this, observer, cancel);
+                var sink = new _(this, observer, cancel);
                 setSink(sink);
-                return sink.Run();
+                return sink.Run(_source);
             }
-        }
 
-        class _ : Sink<IList<TSource>>, IObserver<TSource>
-        {
-            private readonly Buffer<TSource, TBufferClosing> _parent;
-
-            public _(Buffer<TSource, TBufferClosing> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                _parent = parent;
-            }
+                private readonly object _gate = new object();
+                private readonly AsyncLock _bufferGate = new AsyncLock();
+                private readonly SerialDisposable _bufferClosingSubscription = new SerialDisposable();
 
-            private IList<TSource> _buffer;
-            private object _gate;
-            private AsyncLock _bufferGate;
+                private readonly Func<IObservable<TBufferClosing>> _bufferClosingSelector;
 
-            private SerialDisposable _m;
+                public _(Selector parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _bufferClosingSelector = parent._bufferClosingSelector;
+                }
 
-            public IDisposable Run()
-            {
-                _buffer = new List<TSource>();
-                _gate = new object();
-                _bufferGate = new AsyncLock();
+                private IList<TSource> _buffer;
 
-                _m = new SerialDisposable();
-                var groupDisposable = new CompositeDisposable(2) { _m };
+                public IDisposable Run(IObservable<TSource> source)
+                {
+                    _buffer = new List<TSource>();
 
-                groupDisposable.Add(_parent._source.SubscribeSafe(this));
+                    var groupDisposable = StableCompositeDisposable.Create(_bufferClosingSubscription, source.SubscribeSafe(this));
 
-                _bufferGate.Wait(CreateBufferClose);
+                    _bufferGate.Wait(CreateBufferClose);
 
-                return groupDisposable;
-            }
+                    return groupDisposable;
+                }
 
-            private void CreateBufferClose()
-            {
-                var bufferClose = default(IObservable<TBufferClosing>);
-                try
+                private void CreateBufferClose()
                 {
-                    bufferClose = _parent._bufferClosingSelector();
+                    var bufferClose = default(IObservable<TBufferClosing>);
+                    try
+                    {
+                        bufferClose = _bufferClosingSelector();
+                    }
+                    catch (Exception exception)
+                    {
+                        lock (_gate)
+                        {
+                            base._observer.OnError(exception);
+                            base.Dispose();
+                        }
+                        return;
+                    }
+
+                    var closingSubscription = new SingleAssignmentDisposable();
+                    _bufferClosingSubscription.Disposable = closingSubscription;
+                    closingSubscription.Disposable = bufferClose.SubscribeSafe(new BufferClosingObserver(this, closingSubscription));
                 }
-                catch (Exception exception)
+
+                private void CloseBuffer(IDisposable closingSubscription)
                 {
+                    closingSubscription.Dispose();
+
                     lock (_gate)
                     {
-                        base._observer.OnError(exception);
-                        base.Dispose();
+                        var res = _buffer;
+                        _buffer = new List<TSource>();
+                        base._observer.OnNext(res);
                     }
-                    return;
-                }
 
-                var closingSubscription = new SingleAssignmentDisposable();
-                _m.Disposable = closingSubscription;
-                closingSubscription.Disposable = bufferClose.SubscribeSafe(new Omega(this, closingSubscription));
-            }
-
-            private void CloseBuffer(IDisposable closingSubscription)
-            {
-                closingSubscription.Dispose();
+                    _bufferGate.Wait(CreateBufferClose);
+                }
 
-                lock (_gate)
+                private sealed class BufferClosingObserver : IObserver<TBufferClosing>
                 {
-                    var res = _buffer;
-                    _buffer = new List<TSource>();
-                    base._observer.OnNext(res);
-                }
+                    private readonly _ _parent;
+                    private readonly IDisposable _self;
 
-                _bufferGate.Wait(CreateBufferClose);
-            }
+                    public BufferClosingObserver(_ parent, IDisposable self)
+                    {
+                        _parent = parent;
+                        _self = self;
+                    }
 
-            class Omega : IObserver<TBufferClosing>
-            {
-                private readonly _ _parent;
-                private readonly IDisposable _self;
+                    public void OnNext(TBufferClosing value)
+                    {
+                        _parent.CloseBuffer(_self);
+                    }
 
-                public Omega(_ parent, IDisposable self)
-                {
-                    _parent = parent;
-                    _self = self;
+                    public void OnError(Exception error)
+                    {
+                        _parent.OnError(error);
+                    }
+
+                    public void OnCompleted()
+                    {
+                        _parent.CloseBuffer(_self);
+                    }
                 }
 
-                public void OnNext(TBufferClosing value)
+                public void OnNext(TSource value)
                 {
-                    _parent.CloseBuffer(_self);
+                    lock (_gate)
+                    {
+                        _buffer.Add(value);
+                    }
                 }
 
                 public void OnError(Exception error)
                 {
-                    _parent.OnError(error);
+                    lock (_gate)
+                    {
+                        _buffer.Clear();
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
 
                 public void OnCompleted()
                 {
-                    _parent.CloseBuffer(_self);
+                    lock (_gate)
+                    {
+                        base._observer.OnNext(_buffer);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
             }
+        }
 
-            public void OnNext(TSource value)
+        internal sealed class Boundaries : Producer<IList<TSource>>
+        {
+            private readonly IObservable<TSource> _source;
+            private readonly IObservable<TBufferClosing> _bufferBoundaries;
+
+            public Boundaries(IObservable<TSource> source, IObservable<TBufferClosing> bufferBoundaries)
             {
-                lock (_gate)
-                {
-                    _buffer.Add(value);
-                }
+                _source = source;
+                _bufferBoundaries = bufferBoundaries;
             }
 
-            public void OnError(Exception error)
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                lock (_gate)
-                {
-                    _buffer.Clear();
-                    base._observer.OnError(error);
-                    base.Dispose();
-                }
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            public void OnCompleted()
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                lock (_gate)
+                private readonly object _gate = new object();
+
+                public _(IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnNext(_buffer);
-                    base._observer.OnCompleted();
-                    base.Dispose();
                 }
-            }
-        }
-
-        class Beta : Sink<IList<TSource>>, IObserver<TSource>
-        {
-            private readonly Buffer<TSource, TBufferClosing> _parent;
 
-            public Beta(Buffer<TSource, TBufferClosing> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
-            }
+                private IList<TSource> _buffer;
 
-            private IList<TSource> _buffer;
-            private object _gate;
+                public IDisposable Run(Boundaries parent)
+                {
+                    _buffer = new List<TSource>();
 
-            private RefCountDisposable _refCountDisposable;
+                    var sourceSubscription = parent._source.SubscribeSafe(this);
+                    var boundariesSubscription = parent._bufferBoundaries.SubscribeSafe(new BufferClosingObserver(this));
 
-            public IDisposable Run()
-            {
-                _buffer = new List<TSource>();
-                _gate = new object();
+                    return StableCompositeDisposable.Create(sourceSubscription, boundariesSubscription);
+                }
 
-                var d = new CompositeDisposable(2);
-                _refCountDisposable = new RefCountDisposable(d);
+                private sealed class BufferClosingObserver : IObserver<TBufferClosing>
+                {
+                    private readonly _ _parent;
 
-                d.Add(_parent._source.SubscribeSafe(this));
-                d.Add(_parent._bufferBoundaries.SubscribeSafe(new Omega(this)));
+                    public BufferClosingObserver(_ parent)
+                    {
+                        _parent = parent;
+                    }
 
-                return _refCountDisposable;
-            }
+                    public void OnNext(TBufferClosing value)
+                    {
+                        lock (_parent._gate)
+                        {
+                            var res = _parent._buffer;
+                            _parent._buffer = new List<TSource>();
+                            _parent._observer.OnNext(res);
+                        }
+                    }
 
-            class Omega : IObserver<TBufferClosing>
-            {
-                private readonly Beta _parent;
+                    public void OnError(Exception error)
+                    {
+                        _parent.OnError(error);
+                    }
 
-                public Omega(Beta parent)
-                {
-                    _parent = parent;
+                    public void OnCompleted()
+                    {
+                        _parent.OnCompleted();
+                    }
                 }
 
-                public void OnNext(TBufferClosing value)
+                public void OnNext(TSource value)
                 {
-                    lock (_parent._gate)
+                    lock (_gate)
                     {
-                        var res = _parent._buffer;
-                        _parent._buffer = new List<TSource>();
-                        _parent._observer.OnNext(res);
+                        _buffer.Add(value);
                     }
                 }
 
                 public void OnError(Exception error)
                 {
-                    _parent.OnError(error);
+                    lock (_gate)
+                    {
+                        _buffer.Clear();
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
 
                 public void OnCompleted()
                 {
-                    _parent.OnCompleted();
-                }
-            }
-
-            public void OnNext(TSource value)
-            {
-                lock (_gate)
-                {
-                    _buffer.Add(value);
-                }
-            }
-
-            public void OnError(Exception error)
-            {
-                lock (_gate)
-                {
-                    _buffer.Clear();
-                    base._observer.OnError(error);
-                    base.Dispose();
-                }
-            }
-
-            public void OnCompleted()
-            {
-                lock (_gate)
-                {
-                    base._observer.OnNext(_buffer);
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        base._observer.OnNext(_buffer);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
             }
         }

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

@@ -31,27 +31,24 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TResult>, IObserver<TResult>
+        private sealed class _ : Sink<TResult>, IObserver<TResult>
         {
-            private readonly Case<TValue, TResult> _parent;
-
-            public _(Case<TValue, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(Case<TValue, TResult> parent)
             {
                 var result = default(IObservable<TResult>);
                 try
                 {
-                    result = _parent.Eval();
+                    result = parent.Eval();
                 }
                 catch (Exception exception)
                 {

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/Cast.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TResult>, IObserver<TSource>
+        private sealed class _ : Sink<TResult>, IObserver<TSource>
         {
             public _(IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 13 - 13
Rx.NET/Source/src/System.Reactive/Linq/Observable/Catch.cs

@@ -23,7 +23,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return sink.Run(_sources);
         }
 
-        class _ : TailRecursiveSink<TSource>
+        private sealed class _ : TailRecursiveSink<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
@@ -94,30 +94,30 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_handler, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Catch<TSource, TException> _parent;
+            private readonly Func<TException, IObservable<TSource>> _handler;
 
-            public _(Catch<TSource, TException> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(Func<TException, IObservable<TSource>> handler, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _handler = handler;
             }
 
             private SerialDisposable _subscription;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<TSource> source)
             {
                 _subscription = new SerialDisposable();
 
                 var d1 = new SingleAssignmentDisposable();
                 _subscription.Disposable = d1;
-                d1.Disposable = _parent._source.SubscribeSafe(this);
+                d1.Disposable = source.SubscribeSafe(this);
 
                 return _subscription;
             }
@@ -135,7 +135,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var result = default(IObservable<TSource>);
                     try
                     {
-                        result = _parent._handler(e);
+                        result = _handler(e);
                     }
                     catch (Exception ex)
                     {
@@ -146,7 +146,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                     var d = new SingleAssignmentDisposable();
                     _subscription.Disposable = d;
-                    d.Disposable = result.SubscribeSafe(new Impl(this));
+                    d.Disposable = result.SubscribeSafe(new HandlerObserver(this));
                 }
                 else
                 {
@@ -161,11 +161,11 @@ namespace System.Reactive.Linq.ObservableImpl
                 base.Dispose();
             }
 
-            class Impl : IObserver<TSource>
+            private sealed class HandlerObserver : IObserver<TSource>
             {
                 private readonly _ _parent;
 
-                public Impl(_ parent)
+                public HandlerObserver(_ parent)
                 {
                     _parent = parent;
                 }

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

@@ -25,8 +25,10 @@ namespace System.Reactive.Linq.ObservableImpl
             return sink;
         }
 
-        class _ : PushToPullSink<TSource, TResult>
+        private sealed class _ : PushToPullSink<TSource, TResult>
         {
+            // CONSIDER: This sink has a parent reference that can be considered for removal.
+
             private readonly Collect<TSource, TResult> _parent;
 
             public _(Collect<TSource, TResult> parent, IDisposable subscription)

+ 260 - 302
Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.cs

@@ -10,7 +10,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
     /* The following code is generated by a T4 template. */
 
-    #region CombineLatest auto-generated code (4/14/2017 12:18:58 PM)
+    #region CombineLatest auto-generated code (4/17/2017 3:25:27 PM)
 
     internal sealed class CombineLatest<T1, T2, T3, TResult> : Producer<TResult>
     {
@@ -29,26 +29,26 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, TResult> _parent;
+            private readonly Func<T1, T2, T3, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(3, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
             private CombineLatestObserver<T2> _observer2;
             private CombineLatestObserver<T3> _observer3;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3)
             {
                 var subscriptions = new SingleAssignmentDisposable[3];
                 for (int i = 0; i < 3; i++)
@@ -57,18 +57,15 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
                 _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
                 _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value);
         }
     }
 
@@ -91,19 +88,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(4, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -111,7 +108,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T3> _observer3;
             private CombineLatestObserver<T4> _observer4;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4)
             {
                 var subscriptions = new SingleAssignmentDisposable[4];
                 for (int i = 0; i < 4; i++)
@@ -121,19 +118,16 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
                 _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
                 _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value);
         }
     }
 
@@ -158,19 +152,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(5, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -179,7 +173,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T4> _observer4;
             private CombineLatestObserver<T5> _observer5;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5)
             {
                 var subscriptions = new SingleAssignmentDisposable[5];
                 for (int i = 0; i < 5; i++)
@@ -190,20 +184,17 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
                 _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
                 _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value);
         }
     }
 
@@ -230,19 +221,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(6, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -252,7 +243,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T5> _observer5;
             private CombineLatestObserver<T6> _observer6;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6)
             {
                 var subscriptions = new SingleAssignmentDisposable[6];
                 for (int i = 0; i < 6; i++)
@@ -264,21 +255,18 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
                 _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
                 _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value);
         }
     }
 
@@ -307,19 +295,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(7, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -330,7 +318,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T6> _observer6;
             private CombineLatestObserver<T7> _observer7;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7)
             {
                 var subscriptions = new SingleAssignmentDisposable[7];
                 for (int i = 0; i < 7; i++)
@@ -343,22 +331,19 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
                 _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
                 _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value);
         }
     }
 
@@ -389,19 +374,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(8, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -413,7 +398,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T7> _observer7;
             private CombineLatestObserver<T8> _observer8;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8)
             {
                 var subscriptions = new SingleAssignmentDisposable[8];
                 for (int i = 0; i < 8; i++)
@@ -427,23 +412,20 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
                 _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
                 _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value);
         }
     }
 
@@ -476,19 +458,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(9, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -501,7 +483,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T8> _observer8;
             private CombineLatestObserver<T9> _observer9;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9)
             {
                 var subscriptions = new SingleAssignmentDisposable[9];
                 for (int i = 0; i < 9; i++)
@@ -516,24 +498,21 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
                 _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
                 _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value);
         }
     }
 
@@ -568,19 +547,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(10, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -594,7 +573,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T9> _observer9;
             private CombineLatestObserver<T10> _observer10;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10)
             {
                 var subscriptions = new SingleAssignmentDisposable[10];
                 for (int i = 0; i < 10; i++)
@@ -610,25 +589,22 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
                 _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
                 _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
-                subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
+                subscriptions[9].Disposable = source10.SubscribeSafe(_observer10);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value);
         }
     }
 
@@ -665,19 +641,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(11, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -692,7 +668,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T10> _observer10;
             private CombineLatestObserver<T11> _observer11;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11)
             {
                 var subscriptions = new SingleAssignmentDisposable[11];
                 for (int i = 0; i < 11; i++)
@@ -709,26 +685,23 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
                 _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
                 _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
-                subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10);
-                subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
+                subscriptions[9].Disposable = source10.SubscribeSafe(_observer10);
+                subscriptions[10].Disposable = source11.SubscribeSafe(_observer11);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value);
         }
     }
 
@@ -767,19 +740,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(12, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -795,7 +768,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T11> _observer11;
             private CombineLatestObserver<T12> _observer12;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12)
             {
                 var subscriptions = new SingleAssignmentDisposable[12];
                 for (int i = 0; i < 12; i++)
@@ -813,27 +786,24 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
                 _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
                 _observer12 = new CombineLatestObserver<T12>(_gate, this, 11, subscriptions[11]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
-                subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10);
-                subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11);
-                subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
+                subscriptions[9].Disposable = source10.SubscribeSafe(_observer10);
+                subscriptions[10].Disposable = source11.SubscribeSafe(_observer11);
+                subscriptions[11].Disposable = source12.SubscribeSafe(_observer12);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value);
         }
     }
 
@@ -874,19 +844,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(13, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -903,7 +873,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T12> _observer12;
             private CombineLatestObserver<T13> _observer13;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13)
             {
                 var subscriptions = new SingleAssignmentDisposable[13];
                 for (int i = 0; i < 13; i++)
@@ -922,28 +892,25 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
                 _observer12 = new CombineLatestObserver<T12>(_gate, this, 11, subscriptions[11]);
                 _observer13 = new CombineLatestObserver<T13>(_gate, this, 12, subscriptions[12]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
-                subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10);
-                subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11);
-                subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12);
-                subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
+                subscriptions[9].Disposable = source10.SubscribeSafe(_observer10);
+                subscriptions[10].Disposable = source11.SubscribeSafe(_observer11);
+                subscriptions[11].Disposable = source12.SubscribeSafe(_observer12);
+                subscriptions[12].Disposable = source13.SubscribeSafe(_observer13);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value);
         }
     }
 
@@ -986,19 +953,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(14, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -1016,7 +983,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T13> _observer13;
             private CombineLatestObserver<T14> _observer14;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14)
             {
                 var subscriptions = new SingleAssignmentDisposable[14];
                 for (int i = 0; i < 14; i++)
@@ -1036,29 +1003,26 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer12 = new CombineLatestObserver<T12>(_gate, this, 11, subscriptions[11]);
                 _observer13 = new CombineLatestObserver<T13>(_gate, this, 12, subscriptions[12]);
                 _observer14 = new CombineLatestObserver<T14>(_gate, this, 13, subscriptions[13]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
-                subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10);
-                subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11);
-                subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12);
-                subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13);
-                subscriptions[13].Disposable = _parent._source14.SubscribeSafe(_observer14);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
+                subscriptions[9].Disposable = source10.SubscribeSafe(_observer10);
+                subscriptions[10].Disposable = source11.SubscribeSafe(_observer11);
+                subscriptions[11].Disposable = source12.SubscribeSafe(_observer12);
+                subscriptions[12].Disposable = source13.SubscribeSafe(_observer13);
+                subscriptions[13].Disposable = source14.SubscribeSafe(_observer14);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value);
         }
     }
 
@@ -1103,19 +1067,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14, _source15);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(15, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -1134,7 +1098,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T14> _observer14;
             private CombineLatestObserver<T15> _observer15;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, IObservable<T15> source15)
             {
                 var subscriptions = new SingleAssignmentDisposable[15];
                 for (int i = 0; i < 15; i++)
@@ -1155,30 +1119,27 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer13 = new CombineLatestObserver<T13>(_gate, this, 12, subscriptions[12]);
                 _observer14 = new CombineLatestObserver<T14>(_gate, this, 13, subscriptions[13]);
                 _observer15 = new CombineLatestObserver<T15>(_gate, this, 14, subscriptions[14]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
-                subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10);
-                subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11);
-                subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12);
-                subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13);
-                subscriptions[13].Disposable = _parent._source14.SubscribeSafe(_observer14);
-                subscriptions[14].Disposable = _parent._source15.SubscribeSafe(_observer15);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
+                subscriptions[9].Disposable = source10.SubscribeSafe(_observer10);
+                subscriptions[10].Disposable = source11.SubscribeSafe(_observer11);
+                subscriptions[11].Disposable = source12.SubscribeSafe(_observer12);
+                subscriptions[12].Disposable = source13.SubscribeSafe(_observer13);
+                subscriptions[13].Disposable = source14.SubscribeSafe(_observer14);
+                subscriptions[14].Disposable = source15.SubscribeSafe(_observer15);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value);
         }
     }
 
@@ -1225,19 +1186,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14, _source15, _source16);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> _parent;
+            private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> _resultSelector;
 
-            public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(16, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private CombineLatestObserver<T1> _observer1;
@@ -1257,7 +1218,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private CombineLatestObserver<T15> _observer15;
             private CombineLatestObserver<T16> _observer16;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, IObservable<T15> source15, IObservable<T16> source16)
             {
                 var subscriptions = new SingleAssignmentDisposable[16];
                 for (int i = 0; i < 16; i++)
@@ -1279,31 +1240,28 @@ namespace System.Reactive.Linq.ObservableImpl
                 _observer14 = new CombineLatestObserver<T14>(_gate, this, 13, subscriptions[13]);
                 _observer15 = new CombineLatestObserver<T15>(_gate, this, 14, subscriptions[14]);
                 _observer16 = new CombineLatestObserver<T16>(_gate, this, 15, subscriptions[15]);
-                
-                subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
-                subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
-                subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
-                subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4);
-                subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5);
-                subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6);
-                subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7);
-                subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8);
-                subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9);
-                subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10);
-                subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11);
-                subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12);
-                subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13);
-                subscriptions[13].Disposable = _parent._source14.SubscribeSafe(_observer14);
-                subscriptions[14].Disposable = _parent._source15.SubscribeSafe(_observer15);
-                subscriptions[15].Disposable = _parent._source16.SubscribeSafe(_observer16);
+
+                subscriptions[0].Disposable = source1.SubscribeSafe(_observer1);
+                subscriptions[1].Disposable = source2.SubscribeSafe(_observer2);
+                subscriptions[2].Disposable = source3.SubscribeSafe(_observer3);
+                subscriptions[3].Disposable = source4.SubscribeSafe(_observer4);
+                subscriptions[4].Disposable = source5.SubscribeSafe(_observer5);
+                subscriptions[5].Disposable = source6.SubscribeSafe(_observer6);
+                subscriptions[6].Disposable = source7.SubscribeSafe(_observer7);
+                subscriptions[7].Disposable = source8.SubscribeSafe(_observer8);
+                subscriptions[8].Disposable = source9.SubscribeSafe(_observer9);
+                subscriptions[9].Disposable = source10.SubscribeSafe(_observer10);
+                subscriptions[10].Disposable = source11.SubscribeSafe(_observer11);
+                subscriptions[11].Disposable = source12.SubscribeSafe(_observer12);
+                subscriptions[12].Disposable = source13.SubscribeSafe(_observer13);
+                subscriptions[13].Disposable = source14.SubscribeSafe(_observer14);
+                subscriptions[14].Disposable = source15.SubscribeSafe(_observer15);
+                subscriptions[15].Disposable = source16.SubscribeSafe(_observer16);
 
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value, _observer16.Value);
-            }
+            protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value, _observer16.Value);
         }
     }
 

+ 11 - 13
Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.tt

@@ -24,6 +24,7 @@ for (var i = 3; i <= 16; i++)
     var ts = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j));
     var os = string.Join(", ", Enumerable.Range(1, i).Select(j => "IObservable<T" + j + "> source" + j));
     var vs = string.Join(", ", Enumerable.Range(1, i).Select(j => "_observer" + j + ".Value"));
+    var ss = string.Join(", ", Enumerable.Range(1, i).Select(j => "_source" + j));
 #>
     internal sealed class CombineLatest<<#=ts#>, TResult> : Producer<TResult>
     {
@@ -52,19 +53,19 @@ for (var j = 1; j <= i; j++)
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(<#=ss#>);
         }
 
-        class _ : CombineLatestSink<TResult>
+        private sealed class _ : CombineLatestSink<TResult>
         {
-            private readonly CombineLatest<<#=ts#>, TResult> _parent;
+            private readonly Func<<#=ts#>, TResult> _resultSelector;
 
-            public _(CombineLatest<<#=ts#>, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<<#=ts#>, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(<#=i#>, observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
 <#
@@ -76,7 +77,7 @@ for (var j = 1; j <= i; j++)
 }
 #>
 
-            public IDisposable Run()
+            public IDisposable Run(<#=os#>)
             {
                 var subscriptions = new SingleAssignmentDisposable[<#=i#>];
                 for (int i = 0; i < <#=i#>; i++)
@@ -90,12 +91,12 @@ for (var j = 1; j <= i; j++)
 <#
 }
 #>
-                
+
 <#
 for (var j = 1; j <= i; j++)
 {
 #>
-                subscriptions[<#=j - 1#>].Disposable = _parent._source<#=j#>.SubscribeSafe(_observer<#=j#>);
+                subscriptions[<#=j - 1#>].Disposable = source<#=j#>.SubscribeSafe(_observer<#=j#>);
 <#
 }
 #>
@@ -103,10 +104,7 @@ for (var j = 1; j <= i; j++)
                 return StableCompositeDisposable.Create(subscriptions);
             }
 
-            protected override TResult GetResult()
-            {
-                return _parent._resultSelector(<#=vs#>);
-            }
+            protected override TResult GetResult() => _resultSelector(<#=vs#>);
         }
     }
 

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

@@ -26,55 +26,55 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_first, _second);
         }
 
-        class _ : Sink<TResult>
+        private sealed class _ : Sink<TResult>
         {
-            private readonly CombineLatest<TFirst, TSecond, TResult> _parent;
+            private readonly Func<TFirst, TSecond, TResult> _resultSelector;
 
-            public _(CombineLatest<TFirst, TSecond, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<TFirst, TSecond, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private object _gate;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<TFirst> first, IObservable<TSecond> second)
             {
                 _gate = new object();
 
                 var fstSubscription = new SingleAssignmentDisposable();
                 var sndSubscription = new SingleAssignmentDisposable();
 
-                var fstO = new F(this, fstSubscription);
-                var sndO = new S(this, sndSubscription);
+                var fstO = new FirstObserver(this, fstSubscription);
+                var sndO = new SecondObserver(this, sndSubscription);
 
                 fstO.Other = sndO;
                 sndO.Other = fstO;
 
-                fstSubscription.Disposable = _parent._first.SubscribeSafe(fstO);
-                sndSubscription.Disposable = _parent._second.SubscribeSafe(sndO);
+                fstSubscription.Disposable = first.SubscribeSafe(fstO);
+                sndSubscription.Disposable = second.SubscribeSafe(sndO);
 
                 return StableCompositeDisposable.Create(fstSubscription, sndSubscription);
             }
 
-            class F : IObserver<TFirst>
+            private sealed class FirstObserver : IObserver<TFirst>
             {
                 private readonly _ _parent;
                 private readonly IDisposable _self;
-                private S _other;
+                private SecondObserver _other;
 
-                public F(_ parent, IDisposable self)
+                public FirstObserver(_ parent, IDisposable self)
                 {
                     _parent = parent;
                     _self = self;
                 }
 
-                public S Other { set { _other = value; } }
+                public SecondObserver Other { set { _other = value; } }
 
                 public bool HasValue { get; private set; }
                 public TFirst Value { get; private set; }
@@ -92,7 +92,7 @@ namespace System.Reactive.Linq.ObservableImpl
                             var res = default(TResult);
                             try
                             {
-                                res = _parent._parent._resultSelector(value, _other.Value);
+                                res = _parent._resultSelector(value, _other.Value);
                             }
                             catch (Exception ex)
                             {
@@ -141,19 +141,19 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class S : IObserver<TSecond>
+            private sealed class SecondObserver : IObserver<TSecond>
             {
                 private readonly _ _parent;
                 private readonly IDisposable _self;
-                private F _other;
+                private FirstObserver _other;
 
-                public S(_ parent, IDisposable self)
+                public SecondObserver(_ parent, IDisposable self)
                 {
                     _parent = parent;
                     _self = self;
                 }
 
-                public F Other { set { _other = value; } }
+                public FirstObserver Other { set { _other = value; } }
 
                 public bool HasValue { get; private set; }
                 public TSecond Value { get; private set; }
@@ -171,7 +171,7 @@ namespace System.Reactive.Linq.ObservableImpl
                             var res = default(TResult);
                             try
                             {
-                                res = _parent._parent._resultSelector(_other.Value, value);
+                                res = _parent._resultSelector(_other.Value, value);
                             }
                             catch (Exception ex)
                             {
@@ -228,14 +228,14 @@ namespace System.Reactive.Linq.ObservableImpl
 
     #region Helpers for n-ary overloads
 
-    interface ICombineLatest
+    internal interface ICombineLatest
     {
         void Next(int index);
         void Fail(Exception error);
         void Done(int index);
     }
 
-    abstract class CombineLatestSink<TResult> : Sink<TResult>, ICombineLatest
+    internal abstract class CombineLatestSink<TResult> : Sink<TResult>, ICombineLatest
     {
         protected readonly object _gate;
 
@@ -354,10 +354,7 @@ namespace System.Reactive.Linq.ObservableImpl
             _self = self;
         }
 
-        public T Value
-        {
-            get { return _value; }
-        }
+        public T Value => _value;
 
         public void OnNext(T value)
         {
@@ -408,19 +405,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_resultSelector, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_sources);
         }
 
-        class _ : Sink<TResult>
+        private sealed class _ : Sink<TResult>
         {
-            private readonly CombineLatest<TSource, TResult> _parent;
+            private readonly Func<IList<TSource>, TResult> _resultSelector;
 
-            public _(CombineLatest<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Func<IList<TSource>, TResult> resultSelector, IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _resultSelector = resultSelector;
             }
 
             private object _gate;
@@ -430,9 +427,9 @@ namespace System.Reactive.Linq.ObservableImpl
             private bool[] _isDone;
             private IDisposable[] _subscriptions;
 
-            public IDisposable Run()
+            public IDisposable Run(IEnumerable<IObservable<TSource>> sources)
             {
-                var srcs = _parent._sources.ToArray();
+                var srcs = sources.ToArray();
 
                 var N = srcs.Length;
 
@@ -456,7 +453,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var d = new SingleAssignmentDisposable();
                     _subscriptions[j] = d;
 
-                    var o = new O(this, j);
+                    var o = new SourceObserver(this, j);
                     d.Disposable = srcs[j].SubscribeSafe(o);
                 }
 
@@ -471,12 +468,12 @@ namespace System.Reactive.Linq.ObservableImpl
 
                     _hasValue[index] = true;
 
-                    if (_hasValueAll || (_hasValueAll = _hasValue.All(Stubs<bool>.I)))
+                    if (_hasValueAll || (_hasValueAll = _hasValue.All()))
                     {
                         var res = default(TResult);
                         try
                         {
-                            res = _parent._resultSelector(new ReadOnlyCollection<TSource>(_values));
+                            res = _resultSelector(new ReadOnlyCollection<TSource>(_values));
                         }
                         catch (Exception ex)
                         {
@@ -487,7 +484,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                         _observer.OnNext(res);
                     }
-                    else if (_isDone.Where((x, i) => i != index).All(Stubs<bool>.I))
+                    else if (_isDone.AllExcept(index))
                     {
                         base._observer.OnCompleted();
                         base.Dispose();
@@ -511,7 +508,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     _isDone[index] = true;
 
-                    if (_isDone.All(Stubs<bool>.I))
+                    if (_isDone.All())
                     {
                         base._observer.OnCompleted();
                         base.Dispose();
@@ -524,12 +521,41 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class O : IObserver<TSource>
+            private static bool All(bool[] values)
+            {
+                foreach (var value in values)
+                {
+                    if (!value)
+                    {
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+
+            private static bool AllExcept(bool[] values, int index)
+            {
+                for (var i = 0; i < values.Length; i++)
+                {
+                    if (i != index)
+                    {
+                        if (!values[i])
+                        {
+                            return false;
+                        }
+                    }
+                }
+
+                return true;
+            }
+
+            private sealed class SourceObserver : IObserver<TSource>
             {
                 private readonly _ _parent;
                 private readonly int _index;
 
-                public O(_ parent, int index)
+                public SourceObserver(_ parent, int index)
                 {
                     _parent = parent;
                     _index = index;

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

@@ -22,12 +22,9 @@ namespace System.Reactive.Linq.ObservableImpl
             return sink.Run(_sources);
         }
 
-        public IEnumerable<IObservable<TSource>> GetSources()
-        {
-            return _sources;
-        }
+        public IEnumerable<IObservable<TSource>> GetSources() => _sources;
 
-        class _ : ConcatSink<TSource>
+        private sealed class _ : ConcatSink<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

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

@@ -26,14 +26,16 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<bool>, IObserver<TSource>
+        private sealed class _ : Sink<bool>, IObserver<TSource>
         {
-            private readonly Contains<TSource> _parent;
+            private readonly TSource _value;
+            private readonly IEqualityComparer<TSource> _comparer;
 
             public _(Contains<TSource> parent, IObserver<bool> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _value = parent._value;
+                _comparer = parent._comparer;
             }
 
             public void OnNext(TSource value)
@@ -41,7 +43,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 var res = false;
                 try
                 {
-                    res = _parent._comparer.Equals(value, _parent._value);
+                    res = _comparer.Equals(value, _value);
                 }
                 catch (Exception ex)
                 {

+ 83 - 75
Rx.NET/Source/src/System.Reactive/Linq/Observable/Count.cs

@@ -4,118 +4,126 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Count<TSource> : Producer<int>
+    internal static class Count<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-
-        public Count(IObservable<TSource> source)
+        internal sealed class All : Producer<int>
         {
-            _source = source;
-        }
+            private readonly IObservable<TSource> _source;
 
-        public Count(IObservable<TSource> source, Func<TSource, bool> predicate)
-        {
-            _source = source;
-            _predicate = predicate;
-        }
-
-        protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate == null)
+            public All(IObservable<TSource> source)
             {
-                var sink = new _(observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
             }
-            else
+
+            protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new CountImpl(this, observer, cancel);
+                var sink = new _(observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
-
-        class _ : Sink<int>, IObserver<TSource>
-        {
-            private int _count;
 
-            public _(IObserver<int> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<int>, IObserver<TSource>
             {
-                _count = 0;
-            }
+                private int _count;
 
-            public void OnNext(TSource value)
-            {
-                try
+                public _(IObserver<int> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    checked
+                    _count = 0;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    try
                     {
-                        _count++;
+                        checked
+                        {
+                            _count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
                     }
                 }
-                catch (Exception ex)
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(ex);
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
 
-            public void OnCompleted()
-            {
-                base._observer.OnNext(_count);
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_count);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class CountImpl : Sink<int>, IObserver<TSource>
+        internal sealed class Predicate : Producer<int>
         {
-            private readonly Count<TSource> _parent;
-            private int _count;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
 
-            public CountImpl(Count<TSource> parent, IObserver<int> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
             {
-                _parent = parent;
-                _count = 0;
+                _source = source;
+                _predicate = predicate;
             }
 
-            public void OnNext(TSource value)
+            protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                try
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<int>, IObserver<TSource>
+            {
+                private readonly Func<TSource, bool> _predicate;
+                private int _count;
+
+                public _(Func<TSource, bool> predicate, IObserver<int> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _predicate = predicate;
+                    _count = 0;
+                }
+
+                public void OnNext(TSource value)
                 {
-                    checked
+                    try
                     {
-                        if (_parent._predicate(value))
-                            _count++;
+                        checked
+                        {
+                            if (_predicate(value))
+                            {
+                                _count++;
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
                     }
                 }
-                catch (Exception ex)
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(ex);
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
-
-            public void OnCompleted()
-            {
-                base._observer.OnNext(_count);
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_count);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

+ 6 - 6
Rx.NET/Source/src/System.Reactive/Linq/Observable/DefaultIfEmpty.cs

@@ -17,20 +17,20 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_defaultValue, observer, cancel);
             setSink(sink);
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly DefaultIfEmpty<TSource> _parent;
+            private readonly TSource _defaultValue;
             private bool _found;
 
-            public _(DefaultIfEmpty<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(TSource defaultValue, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _defaultValue = defaultValue;
                 _found = false;
             }
 
@@ -49,7 +49,7 @@ namespace System.Reactive.Linq.ObservableImpl
             public void OnCompleted()
             {
                 if (!_found)
-                    base._observer.OnNext(_parent._defaultValue);
+                    base._observer.OnNext(_defaultValue);
                 base._observer.OnCompleted();
                 base.Dispose();
             }

+ 7 - 10
Rx.NET/Source/src/System.Reactive/Linq/Observable/Defer.cs

@@ -17,24 +17,21 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TValue> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_observableFactory, observer, cancel);
             setSink(sink);
             return sink.Run();
         }
 
-        public IObservable<TValue> Eval()
-        {
-            return _observableFactory();
-        }
+        public IObservable<TValue> Eval() => _observableFactory();
 
-        class _ : Sink<TValue>, IObserver<TValue>
+        private sealed class _ : Sink<TValue>, IObserver<TValue>
         {
-            private readonly Defer<TValue> _parent;
+            private readonly Func<IObservable<TValue>> _observableFactory;
 
-            public _(Defer<TValue> parent, IObserver<TValue> observer, IDisposable cancel)
+            public _(Func<IObservable<TValue>> observableFactory, IObserver<TValue> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _observableFactory = observableFactory;
             }
 
             public IDisposable Run()
@@ -42,7 +39,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 var result = default(IObservable<TValue>);
                 try
                 {
-                    result = _parent.Eval();
+                    result = _observableFactory();
                 }
                 catch (Exception exception)
                 {

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

@@ -9,720 +9,817 @@ using System.Threading;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Delay<TSource> : Producer<TSource>
+    internal static class Delay<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly TimeSpan? _dueTimeR;
-        private readonly DateTimeOffset? _dueTimeA;
-        private readonly IScheduler _scheduler;
-
-        public Delay(IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
+        internal abstract class Base : Producer<TSource>
         {
-            _source = source;
-            _dueTimeR = dueTime;
-            _scheduler = scheduler;
-        }
+            protected readonly IObservable<TSource> _source;
+            protected readonly IScheduler _scheduler;
 
-        public Delay(IObservable<TSource> source, DateTimeOffset dueTime, IScheduler scheduler)
-        {
-            _source = source;
-            _dueTimeA = dueTime;
-            _scheduler = scheduler;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_scheduler.AsLongRunning() != null)
+            public Base(IObservable<TSource> source, IScheduler scheduler)
             {
-                var sink = new LongRunningImpl(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _source = source;
+                _scheduler = scheduler;
             }
-            else
-            {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
-            }
-        }
 
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly Delay<TSource> _parent;
-
-            public _(Delay<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected abstract class _<TParent> : Sink<TSource>, IObserver<TSource>
+                where TParent : Base
             {
-                _parent = parent;
-            }
+                protected readonly object _gate = new object();
+                protected readonly SerialDisposable _cancelable = new SerialDisposable();
 
-            private IScheduler _scheduler;
-            private IDisposable _sourceSubscription;
-            private SerialDisposable _cancelable;
-            private TimeSpan _delay;
-            private IStopwatch _watch;
-
-            private object _gate;
-            private bool _ready;
-            private bool _active;
-            private bool _running;
-            private Queue<System.Reactive.TimeInterval<TSource>> _queue;
-            private bool _hasCompleted;
-            private TimeSpan _completeAt;
-            private bool _hasFailed;
-            private Exception _exception;
-
-            public IDisposable Run()
-            {
-                _scheduler = _parent._scheduler;
+                protected readonly IScheduler _scheduler;
 
-                _cancelable = new SerialDisposable();
+                public _(TParent parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _scheduler = parent._scheduler;
+                }
 
-                _gate = new object();
-                _active = false;
-                _running = false;
-                _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
-                _hasCompleted = false;
-                _completeAt = default(TimeSpan);
-                _hasFailed = false;
-                _exception = default(Exception);
+                private IDisposable _sourceSubscription;
 
-                _watch = _scheduler.StartStopwatch();
+                protected IStopwatch _watch;
+                protected TimeSpan _delay;
+                protected bool _ready;
+                protected bool _active;
+                protected bool _running;
+                protected Queue<System.Reactive.TimeInterval<TSource>> _queue = new Queue<Reactive.TimeInterval<TSource>>();
 
-                if (_parent._dueTimeA.HasValue)
-                {
-                    _ready = false;
+                private bool _hasCompleted;
+                private TimeSpan _completeAt;
+                private bool _hasFailed;
+                private Exception _exception;
 
-                    var dueTimeA = _parent._dueTimeA.Value;
-                    _cancelable.Disposable = _scheduler.Schedule(dueTimeA, Start);
-                }
-                else
+                public IDisposable Run(TParent parent)
                 {
-                    _ready = true;
+                    _active = false;
+                    _running = false;
+                    _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+                    _hasCompleted = false;
+                    _completeAt = default(TimeSpan);
+                    _hasFailed = false;
+                    _exception = default(Exception);
+
+                    _watch = _scheduler.StartStopwatch();
+
+                    RunCore(parent);
 
-                    var dueTimeR = _parent._dueTimeR.Value;
-                    _delay = Scheduler.Normalize(dueTimeR);
+                    var sourceSubscription = new SingleAssignmentDisposable();
+                    _sourceSubscription = sourceSubscription;
+                    sourceSubscription.Disposable = parent._source.SubscribeSafe(this);
+
+                    return StableCompositeDisposable.Create(_sourceSubscription, _cancelable);
                 }
 
-                var sourceSubscription = new SingleAssignmentDisposable();
-                _sourceSubscription = sourceSubscription;
-                sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+                protected abstract void RunCore(TParent parent);
 
-                return StableCompositeDisposable.Create(_sourceSubscription, _cancelable);
-            }
+                public void OnNext(TSource value)
+                {
+                    var next = _watch.Elapsed.Add(_delay);
+                    var shouldRun = false;
 
-            private void Start()
-            {
-                var next = default(TimeSpan);
-                var shouldRun = false;
+                    lock (_gate)
+                    {
+                        _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, next));
+
+                        shouldRun = _ready && !_active;
+                        _active = true;
+                    }
+
+                    if (shouldRun)
+                    {
+                        _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue);
+                    }
+                }
 
-                lock (_gate)
+                public void OnError(Exception error)
                 {
-                    _delay = _watch.Elapsed;
+                    _sourceSubscription.Dispose();
 
-                    var oldQueue = _queue;
-                    _queue = new Queue<Reactive.TimeInterval<TSource>>();
+                    var shouldRun = false;
 
-                    if (oldQueue.Count > 0)
+                    lock (_gate)
                     {
-                        next = oldQueue.Peek().Interval;
+                        _queue.Clear();
 
-                        while (oldQueue.Count > 0)
-                        {
-                            var item = oldQueue.Dequeue();
-                            _queue.Enqueue(new Reactive.TimeInterval<TSource>(item.Value, item.Interval.Add(_delay)));
-                        }
+                        _exception = error;
+                        _hasFailed = true;
 
-                        shouldRun = true;
-                        _active = true;
+                        shouldRun = !_running;
                     }
 
-                    _ready = true;
+                    if (shouldRun)
+                    {
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
 
-                if (shouldRun)
+                public void OnCompleted()
                 {
-                    _cancelable.Disposable = _scheduler.Schedule(next, DrainQueue);
-                }
-            }
+                    _sourceSubscription.Dispose();
 
-            public void OnNext(TSource value)
-            {
-                var next = _watch.Elapsed.Add(_delay);
-                var shouldRun = false;
+                    var next = _watch.Elapsed.Add(_delay);
+                    var shouldRun = false;
 
-                lock (_gate)
-                {
-                    _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, next));
+                    lock (_gate)
+                    {
+                        _completeAt = next;
+                        _hasCompleted = true;
+
+                        shouldRun = _ready && !_active;
+                        _active = true;
+                    }
 
-                    shouldRun = _ready && !_active;
-                    _active = true;
+                    if (shouldRun)
+                    {
+                        _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue);
+                    }
                 }
 
-                if (shouldRun)
+                protected void DrainQueue(Action<TimeSpan> recurse)
                 {
-                    _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue);
+                    lock (_gate)
+                    {
+                        if (_hasFailed)
+                            return;
+                        _running = true;
+                    }
+
+                    //
+                    // The shouldYield flag was added to address TFS 487881: "Delay can be unfair". In the old
+                    // implementation, the loop below kept running while there was work for immediate dispatch,
+                    // potentially causing a long running work item on the target scheduler. With the addition
+                    // of long-running scheduling in Rx v2.0, we can check whether the scheduler supports this
+                    // interface and perform different processing (see LongRunningImpl). To reduce the code 
+                    // churn in the old loop code here, we set the shouldYield flag to true after the first 
+                    // dispatch iteration, in order to break from the loop and enter the recursive scheduling path.
+                    //
+                    var shouldYield = false;
+
+                    while (true)
+                    {
+                        var hasFailed = false;
+                        var error = default(Exception);
+
+                        var hasValue = false;
+                        var value = default(TSource);
+                        var hasCompleted = false;
+
+                        var shouldRecurse = false;
+                        var recurseDueTime = default(TimeSpan);
+
+                        lock (_gate)
+                        {
+                            if (_hasFailed)
+                            {
+                                error = _exception;
+                                hasFailed = true;
+                                _running = false;
+                            }
+                            else
+                            {
+                                var now = _watch.Elapsed;
+
+                                if (_queue.Count > 0)
+                                {
+                                    var nextDue = _queue.Peek().Interval;
+
+                                    if (nextDue.CompareTo(now) <= 0 && !shouldYield)
+                                    {
+                                        value = _queue.Dequeue().Value;
+                                        hasValue = true;
+                                    }
+                                    else
+                                    {
+                                        shouldRecurse = true;
+                                        recurseDueTime = Scheduler.Normalize(nextDue.Subtract(now));
+                                        _running = false;
+                                    }
+                                }
+                                else if (_hasCompleted)
+                                {
+                                    if (_completeAt.CompareTo(now) <= 0 && !shouldYield)
+                                    {
+                                        hasCompleted = true;
+                                    }
+                                    else
+                                    {
+                                        shouldRecurse = true;
+                                        recurseDueTime = Scheduler.Normalize(_completeAt.Subtract(now));
+                                        _running = false;
+                                    }
+                                }
+                                else
+                                {
+                                    _running = false;
+                                    _active = false;
+                                }
+                            }
+                        } /* lock (_gate) */
+
+                        if (hasValue)
+                        {
+                            base._observer.OnNext(value);
+                            shouldYield = true;
+                        }
+                        else
+                        {
+                            if (hasCompleted)
+                            {
+                                base._observer.OnCompleted();
+                                base.Dispose();
+                            }
+                            else if (hasFailed)
+                            {
+                                base._observer.OnError(error);
+                                base.Dispose();
+                            }
+                            else if (shouldRecurse)
+                            {
+                                recurse(recurseDueTime);
+                            }
+
+                            return;
+                        }
+                    } /* while (true) */
                 }
             }
 
-            public void OnError(Exception error)
+            protected abstract class L<TParent> : Sink<TSource>, IObserver<TSource>
+                where TParent : Base
             {
-                _sourceSubscription.Dispose();
+                protected readonly object _gate = new object();
+                protected readonly SerialDisposable _cancelable = new SerialDisposable();
+                private readonly SemaphoreSlim _evt = new SemaphoreSlim(0);
 
-                var shouldRun = false;
+                private readonly IScheduler _scheduler;
 
-                lock (_gate)
+                public L(TParent parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    _queue.Clear();
+                    _scheduler = parent._scheduler;
+                }
 
-                    _exception = error;
-                    _hasFailed = true;
+                private IDisposable _sourceSubscription;
 
-                    shouldRun = !_running;
-                }
+                protected IStopwatch _watch;
+                protected TimeSpan _delay;
+                protected Queue<System.Reactive.TimeInterval<TSource>> _queue;
+
+                private CancellationTokenSource _stop;
+                private bool _hasCompleted;
+                private TimeSpan _completeAt;
+                private bool _hasFailed;
+                private Exception _exception;
 
-                if (shouldRun)
+                public IDisposable Run(TParent parent)
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
-                }
-            }
+                    _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+                    _hasCompleted = false;
+                    _completeAt = default(TimeSpan);
+                    _hasFailed = false;
+                    _exception = default(Exception);
 
-            public void OnCompleted()
-            {
-                _sourceSubscription.Dispose();
+                    _watch = _scheduler.StartStopwatch();
 
-                var next = _watch.Elapsed.Add(_delay);
-                var shouldRun = false;
+                    RunCore(parent);
 
-                lock (_gate)
-                {
-                    _completeAt = next;
-                    _hasCompleted = true;
+                    var sourceSubscription = new SingleAssignmentDisposable();
+                    _sourceSubscription = sourceSubscription;
+                    sourceSubscription.Disposable = parent._source.SubscribeSafe(this);
 
-                    shouldRun = _ready && !_active;
-                    _active = true;
+                    return StableCompositeDisposable.Create(_sourceSubscription, _cancelable);
                 }
 
-                if (shouldRun)
+                protected abstract void RunCore(TParent parent);
+
+                protected void ScheduleDrain()
                 {
-                    _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue);
+                    _stop = new CancellationTokenSource();
+                    _cancelable.Disposable = Disposable.Create(_stop.Cancel);
+
+                    _scheduler.AsLongRunning().ScheduleLongRunning(DrainQueue);
                 }
-            }
 
-            private void DrainQueue(Action<TimeSpan> recurse)
-            {
-                lock (_gate)
+                public void OnNext(TSource value)
                 {
-                    if (_hasFailed)
-                        return;
-                    _running = true;
-                }
+                    var next = _watch.Elapsed.Add(_delay);
+
+                    lock (_gate)
+                    {
+                        _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, next));
 
-                //
-                // The shouldYield flag was added to address TFS 487881: "Delay can be unfair". In the old
-                // implementation, the loop below kept running while there was work for immediate dispatch,
-                // potentially causing a long running work item on the target scheduler. With the addition
-                // of long-running scheduling in Rx v2.0, we can check whether the scheduler supports this
-                // interface and perform different processing (see LongRunningImpl). To reduce the code 
-                // churn in the old loop code here, we set the shouldYield flag to true after the first 
-                // dispatch iteration, in order to break from the loop and enter the recursive scheduling path.
-                //
-                var shouldYield = false;
+                        _evt.Release();
+                    }
+                }
 
-                while (true)
+                public void OnError(Exception error)
                 {
-                    var hasFailed = false;
-                    var error = default(Exception);
+                    _sourceSubscription.Dispose();
+
+                    lock (_gate)
+                    {
+                        _queue.Clear();
+
+                        _exception = error;
+                        _hasFailed = true;
 
-                    var hasValue = false;
-                    var value = default(TSource);
-                    var hasCompleted = false;
+                        _evt.Release();
+                    }
+                }
+
+                public void OnCompleted()
+                {
+                    _sourceSubscription.Dispose();
 
-                    var shouldRecurse = false;
-                    var recurseDueTime = default(TimeSpan);
+                    var next = _watch.Elapsed.Add(_delay);
 
                     lock (_gate)
                     {
-                        if (_hasFailed)
+                        _completeAt = next;
+                        _hasCompleted = true;
+
+                        _evt.Release();
+                    }
+                }
+
+                private void DrainQueue(ICancelable cancel)
+                {
+                    while (true)
+                    {
+                        try
                         {
-                            error = _exception;
-                            hasFailed = true;
-                            _running = false;
+                            _evt.Wait(_stop.Token);
                         }
-                        else
+                        catch (OperationCanceledException)
                         {
-                            var now = _watch.Elapsed;
+                            return;
+                        }
 
-                            if (_queue.Count > 0)
+                        var hasFailed = false;
+                        var error = default(Exception);
+
+                        var hasValue = false;
+                        var value = default(TSource);
+                        var hasCompleted = false;
+
+                        var shouldWait = false;
+                        var waitTime = default(TimeSpan);
+
+                        lock (_gate)
+                        {
+                            if (_hasFailed)
                             {
-                                var nextDue = _queue.Peek().Interval;
+                                error = _exception;
+                                hasFailed = true;
+                            }
+                            else
+                            {
+                                var now = _watch.Elapsed;
 
-                                if (nextDue.CompareTo(now) <= 0 && !shouldYield)
+                                if (_queue.Count > 0)
                                 {
-                                    value = _queue.Dequeue().Value;
+                                    var next = _queue.Dequeue();
+
                                     hasValue = true;
+                                    value = next.Value;
+
+                                    var nextDue = next.Interval;
+                                    if (nextDue.CompareTo(now) > 0)
+                                    {
+                                        shouldWait = true;
+                                        waitTime = Scheduler.Normalize(nextDue.Subtract(now));
+                                    }
                                 }
-                                else
+                                else if (_hasCompleted)
                                 {
-                                    shouldRecurse = true;
-                                    recurseDueTime = Scheduler.Normalize(nextDue.Subtract(now));
-                                    _running = false;
+                                    hasCompleted = true;
+
+                                    if (_completeAt.CompareTo(now) > 0)
+                                    {
+                                        shouldWait = true;
+                                        waitTime = Scheduler.Normalize(_completeAt.Subtract(now));
+                                    }
                                 }
                             }
-                            else if (_hasCompleted)
+                        } /* lock (_gate) */
+
+                        if (shouldWait)
+                        {
+                            var timer = new ManualResetEventSlim();
+                            _scheduler.Schedule(waitTime, () => { timer.Set(); });
+
+                            try
                             {
-                                if (_completeAt.CompareTo(now) <= 0 && !shouldYield)
-                                {
-                                    hasCompleted = true;
-                                }
-                                else
-                                {
-                                    shouldRecurse = true;
-                                    recurseDueTime = Scheduler.Normalize(_completeAt.Subtract(now));
-                                    _running = false;
-                                }
+                                timer.Wait(_stop.Token);
                             }
-                            else
+                            catch (OperationCanceledException)
                             {
-                                _running = false;
-                                _active = false;
+                                return;
                             }
                         }
-                    } /* lock (_gate) */
 
-                    if (hasValue)
-                    {
-                        base._observer.OnNext(value);
-                        shouldYield = true;
-                    }
-                    else
-                    {
-                        if (hasCompleted)
+                        if (hasValue)
                         {
-                            base._observer.OnCompleted();
-                            base.Dispose();
+                            base._observer.OnNext(value);
                         }
-                        else if (hasFailed)
-                        {
-                            base._observer.OnError(error);
-                            base.Dispose();
-                        }
-                        else if (shouldRecurse)
+                        else
                         {
-                            recurse(recurseDueTime);
-                        }
+                            if (hasCompleted)
+                            {
+                                base._observer.OnCompleted();
+                                base.Dispose();
+                            }
+                            else if (hasFailed)
+                            {
+                                base._observer.OnError(error);
+                                base.Dispose();
+                            }
 
-                        return;
+                            return;
+                        }
                     }
-                } /* while (true) */
+                }
             }
         }
 
-        class LongRunningImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Absolute : Base
         {
-            private readonly Delay<TSource> _parent;
+            private readonly DateTimeOffset _dueTime;
 
-            public LongRunningImpl(Delay<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Absolute(IObservable<TSource> source, DateTimeOffset dueTime, IScheduler scheduler)
+                : base(source, scheduler)
             {
-                _parent = parent;
+                _dueTime = dueTime;
             }
 
-            private IDisposable _sourceSubscription;
-            private SerialDisposable _cancelable;
-            private TimeSpan _delay;
-            private IStopwatch _watch;
-
-            private object _gate;
-            private SemaphoreSlim _evt;
-            private CancellationTokenSource _stop;
-            private Queue<System.Reactive.TimeInterval<TSource>> _queue;
-            private bool _hasCompleted;
-            private TimeSpan _completeAt;
-            private bool _hasFailed;
-            private Exception _exception;
-
-            public IDisposable Run()
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _cancelable = new SerialDisposable();
-
-                _gate = new object();
-                _evt = new SemaphoreSlim(0);
-                _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
-                _hasCompleted = false;
-                _completeAt = default(TimeSpan);
-                _hasFailed = false;
-                _exception = default(Exception);
-
-                _watch = _parent._scheduler.StartStopwatch();
-
-                if (_parent._dueTimeA.HasValue)
+                if (_scheduler.AsLongRunning() != null)
                 {
-                    var dueTimeA = _parent._dueTimeA.Value;
-                    _cancelable.Disposable = _parent._scheduler.Schedule(dueTimeA, Start);
+                    var sink = new L(this, observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this);
                 }
                 else
                 {
-                    var dueTimeR = _parent._dueTimeR.Value;
-                    _delay = Scheduler.Normalize(dueTimeR);
-                    ScheduleDrain();
+                    var sink = new _(this, observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this);
                 }
-
-                var sourceSubscription = new SingleAssignmentDisposable();
-                _sourceSubscription = sourceSubscription;
-                sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
-
-                return StableCompositeDisposable.Create(_sourceSubscription, _cancelable);
             }
 
-            private void Start()
+            private sealed class _ : _<Absolute>
             {
-                lock (_gate)
+                public _(Absolute parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(parent, observer, cancel)
                 {
-                    _delay = _watch.Elapsed;
-
-                    var oldQueue = _queue;
-                    _queue = new Queue<Reactive.TimeInterval<TSource>>();
-
-                    while (oldQueue.Count > 0)
-                    {
-                        var item = oldQueue.Dequeue();
-                        _queue.Enqueue(new Reactive.TimeInterval<TSource>(item.Value, item.Interval.Add(_delay)));
-                    }
                 }
 
-                ScheduleDrain();
-            }
-
-            private void ScheduleDrain()
-            {
-                _stop = new CancellationTokenSource();
-                _cancelable.Disposable = Disposable.Create(() => _stop.Cancel());
-
-                _parent._scheduler.AsLongRunning().ScheduleLongRunning(DrainQueue);
-            }
-
-            public void OnNext(TSource value)
-            {
-                var next = _watch.Elapsed.Add(_delay);
-
-                lock (_gate)
+                protected override void RunCore(Absolute parent)
                 {
-                    _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, next));
+                    _ready = false;
 
-                    _evt.Release();
+                    _cancelable.Disposable = parent._scheduler.Schedule(parent._dueTime, Start);
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                _sourceSubscription.Dispose();
-
-                lock (_gate)
+                private void Start()
                 {
-                    _queue.Clear();
+                    var next = default(TimeSpan);
+                    var shouldRun = false;
 
-                    _exception = error;
-                    _hasFailed = true;
+                    lock (_gate)
+                    {
+                        _delay = _watch.Elapsed;
 
-                    _evt.Release();
-                }
-            }
+                        var oldQueue = _queue;
+                        _queue = new Queue<Reactive.TimeInterval<TSource>>();
 
-            public void OnCompleted()
-            {
-                _sourceSubscription.Dispose();
+                        if (oldQueue.Count > 0)
+                        {
+                            next = oldQueue.Peek().Interval;
 
-                var next = _watch.Elapsed.Add(_delay);
+                            while (oldQueue.Count > 0)
+                            {
+                                var item = oldQueue.Dequeue();
+                                _queue.Enqueue(new Reactive.TimeInterval<TSource>(item.Value, item.Interval.Add(_delay)));
+                            }
 
-                lock (_gate)
-                {
-                    _completeAt = next;
-                    _hasCompleted = true;
+                            shouldRun = true;
+                            _active = true;
+                        }
 
-                    _evt.Release();
+                        _ready = true;
+                    }
+
+                    if (shouldRun)
+                    {
+                        _cancelable.Disposable = _scheduler.Schedule(next, DrainQueue);
+                    }
                 }
             }
 
-            private void DrainQueue(ICancelable cancel)
+            private sealed class L : L<Absolute>
             {
-                while (true)
+                public L(Absolute parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(parent, observer, cancel)
                 {
-                    try
-                    {
-                        _evt.Wait(_stop.Token);
-                    }
-                    catch (OperationCanceledException)
-                    {
-                        return;
-                    }
-
-                    var hasFailed = false;
-                    var error = default(Exception);
-
-                    var hasValue = false;
-                    var value = default(TSource);
-                    var hasCompleted = false;
+                }
 
-                    var shouldWait = false;
-                    var waitTime = default(TimeSpan);
+                protected override void RunCore(Absolute parent)
+                {
+                    _cancelable.Disposable = parent._scheduler.Schedule(parent._dueTime, Start);
+                }
 
+                private void Start()
+                {
                     lock (_gate)
                     {
-                        if (_hasFailed)
-                        {
-                            error = _exception;
-                            hasFailed = true;
-                        }
-                        else
-                        {
-                            var now = _watch.Elapsed;
-
-                            if (_queue.Count > 0)
-                            {
-                                var next = _queue.Dequeue();
-
-                                hasValue = true;
-                                value = next.Value;
+                        _delay = _watch.Elapsed;
 
-                                var nextDue = next.Interval;
-                                if (nextDue.CompareTo(now) > 0)
-                                {
-                                    shouldWait = true;
-                                    waitTime = Scheduler.Normalize(nextDue.Subtract(now));
-                                }
-                            }
-                            else if (_hasCompleted)
-                            {
-                                hasCompleted = true;
+                        var oldQueue = _queue;
+                        _queue = new Queue<Reactive.TimeInterval<TSource>>();
 
-                                if (_completeAt.CompareTo(now) > 0)
-                                {
-                                    shouldWait = true;
-                                    waitTime = Scheduler.Normalize(_completeAt.Subtract(now));
-                                }
-                            }
-                        }
-                    } /* lock (_gate) */
-
-                    if (shouldWait)
-                    {
-                        var timer = new ManualResetEventSlim();
-                        _parent._scheduler.Schedule(waitTime, () => { timer.Set(); });
-
-                        try
-                        {
-                            timer.Wait(_stop.Token);
-                        }
-                        catch (OperationCanceledException)
+                        while (oldQueue.Count > 0)
                         {
-                            return;
+                            var item = oldQueue.Dequeue();
+                            _queue.Enqueue(new Reactive.TimeInterval<TSource>(item.Value, item.Interval.Add(_delay)));
                         }
                     }
 
-                    if (hasValue)
-                    {
-                        base._observer.OnNext(value);
-                    }
-                    else
-                    {
-                        if (hasCompleted)
-                        {
-                            base._observer.OnCompleted();
-                            base.Dispose();
-                        }
-                        else if (hasFailed)
-                        {
-                            base._observer.OnError(error);
-                            base.Dispose();
-                        }
-
-                        return;
-                    }
+                    ScheduleDrain();
                 }
             }
         }
-    }
-
-    internal sealed class Delay<TSource, TDelay> : Producer<TSource>
-    {
-        private readonly IObservable<TSource> _source;
-        private readonly IObservable<TDelay> _subscriptionDelay;
-        private readonly Func<TSource, IObservable<TDelay>> _delaySelector;
-
-        public Delay(IObservable<TSource> source, IObservable<TDelay> subscriptionDelay, Func<TSource, IObservable<TDelay>> delaySelector)
-        {
-            _source = source;
-            _subscriptionDelay = subscriptionDelay;
-            _delaySelector = delaySelector;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            var sink = new _(this, observer, cancel);
-            setSink(sink);
-            return sink.Run();
-        }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        internal sealed class Relative : Base
         {
-            private readonly Delay<TSource, TDelay> _parent;
+            private readonly TimeSpan _dueTime;
 
-            public _(Delay<TSource, TDelay> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Relative(IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
+                : base(source, scheduler)
             {
-                _parent = parent;
+                _dueTime = dueTime;
             }
 
-            private CompositeDisposable _delays;
-            private object _gate;
-            private bool _atEnd;
-            private SerialDisposable _subscription;
-
-            public IDisposable Run()
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _delays = new CompositeDisposable();
-                _gate = new object();
-                _atEnd = false;
-                _subscription = new SerialDisposable();
-
-                if (_parent._subscriptionDelay == null)
+                if (_scheduler.AsLongRunning() != null)
                 {
-                    Start();
+                    var sink = new L(this, observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this);
                 }
                 else
                 {
-                    _subscription.Disposable = _parent._subscriptionDelay.SubscribeSafe(new SubscriptionDelay(this));
+                    var sink = new _(this, observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this);
                 }
-
-                return StableCompositeDisposable.Create(_subscription, _delays);
-            }
-
-            private void Start()
-            {
-                _subscription.Disposable = _parent._source.SubscribeSafe(this);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : _<Relative>
             {
-                var delay = default(IObservable<TDelay>);
-                try
+                public _(Relative parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(parent, observer, cancel)
                 {
-                    delay = _parent._delaySelector(value);
                 }
-                catch (Exception error)
+
+                protected override void RunCore(Relative parent)
                 {
-                    lock (_gate)
-                    {
-                        base._observer.OnError(error);
-                        base.Dispose();
-                    }
+                    _ready = true;
 
-                    return;
+                    _delay = Scheduler.Normalize(parent._dueTime);
                 }
-
-                var d = new SingleAssignmentDisposable();
-                _delays.Add(d);
-                d.Disposable = delay.SubscribeSafe(new Delta(this, value, d));
             }
 
-            public void OnError(Exception error)
+            private sealed class L : L<Relative>
             {
-                lock (_gate)
+                public L(Relative parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(parent, observer, cancel)
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
+                }
+
+                protected override void RunCore(Relative parent)
+                {
+                    _delay = Scheduler.Normalize(parent._dueTime);
+                    ScheduleDrain();
                 }
             }
+        }
+    }
 
-            public void OnCompleted()
+    internal static class Delay<TSource, TDelay>
+    {
+        internal class Selector : Producer<TSource>
+        {
+            protected readonly IObservable<TSource> _source;
+            private readonly Func<TSource, IObservable<TDelay>> _delaySelector;
+
+            public Selector(IObservable<TSource> source, Func<TSource, IObservable<TDelay>> delaySelector)
             {
-                lock (_gate)
-                {
-                    _atEnd = true;
-                    _subscription.Dispose();
+                _source = source;
+                _delaySelector = delaySelector;
+            }
 
-                    CheckDone();
-                }
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _<Selector>(this, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            private void CheckDone()
+            protected class _<TParent> : Sink<TSource>, IObserver<TSource>
+                where TParent : Selector
             {
-                if (_atEnd && _delays.Count == 0)
+                private readonly CompositeDisposable _delays = new CompositeDisposable();
+                private object _gate = new object();
+
+                private readonly Func<TSource, IObservable<TDelay>> _delaySelector;
+
+                public _(Selector parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                    _delaySelector = parent._delaySelector;
                 }
-            }
 
-            class SubscriptionDelay : IObserver<TDelay>
-            {
-                private readonly _ _parent;
+                private bool _atEnd;
+                private IDisposable _subscription;
 
-                public SubscriptionDelay(_ parent)
+                public IDisposable Run(TParent parent)
                 {
-                    _parent = parent;
+                    _atEnd = false;
+
+                    _subscription = RunCore(parent);
+
+                    return StableCompositeDisposable.Create(_subscription, _delays);
                 }
 
-                public void OnNext(TDelay value)
+                protected virtual IDisposable RunCore(TParent parent)
                 {
-                    _parent.Start();
+                    return parent._source.SubscribeSafe(this);
+                }
+
+                public void OnNext(TSource value)
+                {
+                    var delay = default(IObservable<TDelay>);
+                    try
+                    {
+                        delay = _delaySelector(value);
+                    }
+                    catch (Exception error)
+                    {
+                        lock (_gate)
+                        {
+                            base._observer.OnError(error);
+                            base.Dispose();
+                        }
+
+                        return;
+                    }
+
+                    var d = new SingleAssignmentDisposable();
+                    _delays.Add(d);
+                    d.Disposable = delay.SubscribeSafe(new DelayObserver(this, value, d));
                 }
 
                 public void OnError(Exception error)
                 {
-                    _parent._observer.OnError(error);
-                    _parent.Dispose();
+                    lock (_gate)
+                    {
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
 
                 public void OnCompleted()
                 {
-                    _parent.Start();
+                    lock (_gate)
+                    {
+                        _atEnd = true;
+                        _subscription.Dispose();
+
+                        CheckDone();
+                    }
+                }
+
+                private void CheckDone()
+                {
+                    if (_atEnd && _delays.Count == 0)
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
+                }
+
+                private sealed class DelayObserver : IObserver<TDelay>
+                {
+                    private readonly _<TParent> _parent;
+                    private readonly TSource _value;
+                    private readonly IDisposable _self;
+
+                    public DelayObserver(_<TParent> parent, TSource value, IDisposable self)
+                    {
+                        _parent = parent;
+                        _value = value;
+                        _self = self;
+                    }
+
+                    public void OnNext(TDelay value)
+                    {
+                        lock (_parent._gate)
+                        {
+                            _parent._observer.OnNext(_value);
+
+                            _parent._delays.Remove(_self);
+                            _parent.CheckDone();
+                        }
+                    }
+
+                    public void OnError(Exception error)
+                    {
+                        lock (_parent._gate)
+                        {
+                            _parent._observer.OnError(error);
+                            _parent.Dispose();
+                        }
+                    }
+
+                    public void OnCompleted()
+                    {
+                        lock (_parent._gate)
+                        {
+                            _parent._observer.OnNext(_value);
+
+                            _parent._delays.Remove(_self);
+                            _parent.CheckDone();
+                        }
+                    }
                 }
             }
+        }
 
-            class Delta : IObserver<TDelay>
+        internal sealed class SelectorWithSubscriptionDelay : Selector
+        {
+            private readonly IObservable<TDelay> _subscriptionDelay;
+
+            public SelectorWithSubscriptionDelay(IObservable<TSource> source, IObservable<TDelay> subscriptionDelay, Func<TSource, IObservable<TDelay>> delaySelector)
+                : base(source, delaySelector)
+            {
+                _subscriptionDelay = subscriptionDelay;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                private readonly _ _parent;
-                private readonly TSource _value;
-                private readonly IDisposable _self;
+                var sink = new _(this, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
+            }
 
-                public Delta(_ parent, TSource value, IDisposable self)
+            private sealed class _ : _<SelectorWithSubscriptionDelay>
+            {
+                public _(SelectorWithSubscriptionDelay parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(parent, observer, cancel)
                 {
-                    _parent = parent;
-                    _value = value;
-                    _self = self;
                 }
 
-                public void OnNext(TDelay value)
+                protected override IDisposable RunCore(SelectorWithSubscriptionDelay parent)
                 {
-                    lock (_parent._gate)
-                    {
-                        _parent._observer.OnNext(_value);
+                    var subscription = new SerialDisposable();
 
-                        _parent._delays.Remove(_self);
-                        _parent.CheckDone();
-                    }
+                    subscription.Disposable = parent._subscriptionDelay.SubscribeSafe(new SubscriptionDelayObserver(this, parent._source, subscription));
+
+                    return subscription;
                 }
 
-                public void OnError(Exception error)
+                private sealed class SubscriptionDelayObserver : IObserver<TDelay>
                 {
-                    lock (_parent._gate)
+                    private readonly _ _parent;
+                    private readonly IObservable<TSource> _source;
+                    private readonly SerialDisposable _subscription;
+
+                    public SubscriptionDelayObserver(_ parent, IObservable<TSource> source, SerialDisposable subscription)
+                    {
+                        _parent = parent;
+                        _source = source;
+                        _subscription = subscription;
+                    }
+
+                    public void OnNext(TDelay value)
+                    {
+                        _subscription.Disposable = _source.SubscribeSafe(_parent);
+                    }
+
+                    public void OnError(Exception error)
                     {
                         _parent._observer.OnError(error);
                         _parent.Dispose();
                     }
-                }
 
-                public void OnCompleted()
-                {
-                    lock (_parent._gate)
+                    public void OnCompleted()
                     {
-                        _parent._observer.OnNext(_value);
-
-                        _parent._delays.Remove(_self);
-                        _parent.CheckDone();
+                        _subscription.Disposable = _source.SubscribeSafe(_parent);
                     }
                 }
             }

+ 28 - 17
Rx.NET/Source/src/System.Reactive/Linq/Observable/DelaySubscription.cs

@@ -6,39 +6,50 @@ using System.Reactive.Concurrency;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class DelaySubscription<TSource> : Producer<TSource>
+    internal abstract class DelaySubscription<TSource> : Producer<TSource>
     {
         private readonly IObservable<TSource> _source;
-        private readonly DateTimeOffset? _dueTimeA;
-        private readonly TimeSpan? _dueTimeR;
         private readonly IScheduler _scheduler;
 
-        public DelaySubscription(IObservable<TSource> source, DateTimeOffset dueTime, IScheduler scheduler)
+        public DelaySubscription(IObservable<TSource> source, IScheduler scheduler)
         {
             _source = source;
-            _dueTimeA = dueTime;
             _scheduler = scheduler;
         }
 
-        public DelaySubscription(IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
+        internal sealed class Relative : DelaySubscription<TSource>
         {
-            _source = source;
-            _dueTimeR = dueTime;
-            _scheduler = scheduler;
+            private readonly TimeSpan _dueTime;
+
+            public Relative(IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
+                : base(source, scheduler)
+            {
+                _dueTime = dueTime;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return _scheduler.Schedule(sink, _dueTime, Subscribe);
+            }
         }
 
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+        internal sealed class Absolute : DelaySubscription<TSource>
         {
-            var sink = new _(observer, cancel);
-            setSink(sink);
+            private readonly DateTimeOffset _dueTime;
 
-            if (_dueTimeA.HasValue)
+            public Absolute(IObservable<TSource> source, DateTimeOffset dueTime, IScheduler scheduler)
+                : base(source, scheduler)
             {
-                return _scheduler.Schedule(sink, _dueTimeA.Value, Subscribe);
+                _dueTime = dueTime;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                return _scheduler.Schedule(sink, _dueTimeR.Value, Subscribe);
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return _scheduler.Schedule(sink, _dueTime, Subscribe);
             }
         }
 
@@ -47,7 +58,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/Dematerialize.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<Notification<TSource>>
+        private sealed class _ : Sink<TSource>, IObserver<Notification<TSource>>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

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

@@ -26,16 +26,16 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Distinct<TSource, TKey> _parent;
+            private readonly Func<TSource, TKey> _keySelector;
             private HashSet<TKey> _hashSet;
 
             public _(Distinct<TSource, TKey> parent, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _hashSet = new HashSet<TKey>(_parent._comparer);
+                _keySelector = parent._keySelector;
+                _hashSet = new HashSet<TKey>(parent._comparer);
             }
 
             public void OnNext(TSource value)
@@ -44,7 +44,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 var hasAdded = false;
                 try
                 {
-                    key = _parent._keySelector(value);
+                    key = _keySelector(value);
                     hasAdded = _hashSet.Add(key);
                 }
                 catch (Exception exception)

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

@@ -26,16 +26,20 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly DistinctUntilChanged<TSource, TKey> _parent;
+            private readonly Func<TSource, TKey> _keySelector;
+            private readonly IEqualityComparer<TKey> _comparer;
+
             private TKey _currentKey;
             private bool _hasCurrentKey;
 
             public _(DistinctUntilChanged<TSource, TKey> parent, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _keySelector = parent._keySelector;
+                _comparer = parent._comparer;
+
                 _currentKey = default(TKey);
                 _hasCurrentKey = false;
             }
@@ -45,7 +49,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 var key = default(TKey);
                 try
                 {
-                    key = _parent._keySelector(value);
+                    key = _keySelector(value);
                 }
                 catch (Exception exception)
                 {
@@ -59,7 +63,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     try
                     {
-                        comparerEquals = _parent._comparer.Equals(_currentKey, key);
+                        comparerEquals = _comparer.Equals(_currentKey, key);
                     }
                     catch (Exception exception)
                     {

+ 191 - 48
Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs

@@ -4,86 +4,229 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Do<TSource> : Producer<TSource>
+    internal static class Do<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Action<TSource> _onNext;
-        private readonly Action<Exception> _onError;
-        private readonly Action _onCompleted;
-
-        public Do(IObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
-        {
-            _source = source;
-            _onNext = onNext;
-            _onError = onError;
-            _onCompleted = onCompleted;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+        internal sealed class OnNext : Producer<TSource>
         {
-            var sink = new _(this, observer, cancel);
-            setSink(sink);
-            return _source.SubscribeSafe(sink);
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly Action<TSource> _onNext;
 
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly Do<TSource> _parent;
+            public OnNext(IObservable<TSource> source, Action<TSource> onNext)
+            {
+                _source = source;
+                _onNext = onNext;
+            }
 
-            public _(Do<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _parent = parent;
+                var sink = new _(_onNext, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                try
+                private readonly Action<TSource> _onNext;
+
+                public _(Action<TSource> onNext, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    _parent._onNext(value);
+                    _onNext = onNext;
                 }
-                catch (Exception ex)
+
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnError(ex);
+                    try
+                    {
+                        _onNext(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnNext(value);
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
                     base.Dispose();
-                    return;
                 }
 
-                base._observer.OnNext(value);
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+
+        internal sealed class Observer : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+            private readonly IObserver<TSource> _observer;
+
+            public Observer(IObservable<TSource> source, IObserver<TSource> observer)
+            {
+                _source = source;
+                _observer = observer;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_observer, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnError(Exception error)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                try
+                private readonly IObserver<TSource> _doObserver;
+
+                public _(IObserver<TSource> doObserver, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _doObserver = doObserver;
+                }
+
+                public void OnNext(TSource value)
                 {
-                    _parent._onError(error);
+                    try
+                    {
+                        _doObserver.OnNext(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnNext(value);
                 }
-                catch (Exception ex)
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(ex);
+                    try
+                    {
+                        _doObserver.OnError(error);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnError(error);
                     base.Dispose();
-                    return;
                 }
 
-                base._observer.OnError(error);
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    try
+                    {
+                        _doObserver.OnCompleted();
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
+        }
+
+        internal sealed class Actions : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+            private readonly Action<TSource> _onNext;
+            private readonly Action<Exception> _onError;
+            private readonly Action _onCompleted;
 
-            public void OnCompleted()
+            public Actions(IObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
             {
-                try
+                _source = source;
+                _onNext = onNext;
+                _onError = onError;
+                _onCompleted = onCompleted;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(this, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                // CONSIDER: This sink has a parent reference that can be considered for removal.
+
+                private readonly Actions _parent;
+
+                public _(Actions parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _parent = parent;
+                }
+
+                public void OnNext(TSource value)
                 {
-                    _parent._onCompleted();
+                    try
+                    {
+                        _parent._onNext(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnNext(value);
                 }
-                catch (Exception ex)
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(ex);
+                    try
+                    {
+                        _parent._onError(error);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnError(error);
                     base.Dispose();
-                    return;
                 }
 
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    try
+                    {
+                        _parent._onCompleted();
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/DoWhile.cs

@@ -31,7 +31,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 yield return _source;
         }
 
-        class _ : ConcatSink<TSource>
+        private sealed class _ : ConcatSink<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 6 - 19
Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAt.cs

@@ -8,32 +8,28 @@ namespace System.Reactive.Linq.ObservableImpl
     {
         private readonly IObservable<TSource> _source;
         private readonly int _index;
-        private readonly bool _throwOnEmpty;
 
-        public ElementAt(IObservable<TSource> source, int index, bool throwOnEmpty)
+        public ElementAt(IObservable<TSource> source, int index)
         {
             _source = source;
             _index = index;
-            _throwOnEmpty = throwOnEmpty;
         }
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_index, observer, cancel);
             setSink(sink);
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly ElementAt<TSource> _parent;
             private int _i;
 
-            public _(ElementAt<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(int index, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _i = _parent._index;
+                _i = index;
             }
 
             public void OnNext(TSource value)
@@ -56,16 +52,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void OnCompleted()
             {
-                if (_parent._throwOnEmpty)
-                {
-                    base._observer.OnError(new ArgumentOutOfRangeException("index"));
-                }
-                else
-                {
-                    base._observer.OnNext(default(TSource));
-                    base._observer.OnCompleted();
-                }
-                
+                base._observer.OnError(new ArgumentOutOfRangeException("index"));
                 base.Dispose();
             }
         }

+ 61 - 0
Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAtOrDefault.cs

@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+namespace System.Reactive.Linq.ObservableImpl
+{
+    internal sealed class ElementAtOrDefault<TSource> : Producer<TSource>
+    {
+        private readonly IObservable<TSource> _source;
+        private readonly int _index;
+
+        public ElementAtOrDefault(IObservable<TSource> source, int index)
+        {
+            _source = source;
+            _index = index;
+        }
+
+        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+        {
+            var sink = new _(_index, observer, cancel);
+            setSink(sink);
+            return _source.SubscribeSafe(sink);
+        }
+
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
+        {
+            private int _i;
+
+            public _(int index, IObserver<TSource> observer, IDisposable cancel)
+                : base(observer, cancel)
+            {
+                _i = index;
+            }
+
+            public void OnNext(TSource value)
+            {
+                if (_i == 0)
+                {
+                    base._observer.OnNext(value);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+
+                _i--;
+            }
+
+            public void OnError(Exception error)
+            {
+                base._observer.OnError(error);
+                base.Dispose();
+            }
+
+            public void OnCompleted()
+            {
+                base._observer.OnNext(default(TSource));
+                base._observer.OnCompleted();
+                base.Dispose();
+            }
+        }
+    }
+}

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

@@ -17,24 +17,21 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_scheduler);
         }
 
-        class _ : Sink<TResult>
+        private sealed class _ : Sink<TResult>
         {
-            private readonly Empty<TResult> _parent;
-
-            public _(Empty<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(IScheduler scheduler)
             {
-                return _parent._scheduler.Schedule(Invoke);
+                return scheduler.Schedule(Invoke);
             }
 
             private void Invoke()

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

@@ -19,24 +19,24 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_finallyAction, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Finally<TSource> _parent;
+            private readonly Action _finallyAction;
 
-            public _(Finally<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(Action finallyAction, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _finallyAction = finallyAction;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<TSource> source)
             {
-                var subscription = _parent._source.SubscribeSafe(this);
+                var subscription = source.SubscribeSafe(this);
 
                 return Disposable.Create(() =>
                 {
@@ -46,7 +46,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
                     finally
                     {
-                        _parent._finallyAction();
+                        _finallyAction();
                     }
                 });
             }

+ 69 - 81
Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstAsync.cs

@@ -4,126 +4,114 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class FirstAsync<TSource> : Producer<TSource>
+    internal static class FirstAsync<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-        private readonly bool _throwOnEmpty;
-
-        public FirstAsync(IObservable<TSource> source, Func<TSource, bool> predicate, bool throwOnEmpty)
+        internal sealed class Sequence : Producer<TSource>
         {
-            _source = source;
-            _predicate = predicate;
-            _throwOnEmpty = throwOnEmpty;
-        }
+            private readonly IObservable<TSource> _source;
 
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate != null)
+            public Sequence(IObservable<TSource> source)
             {
-                var sink = new FirstAsyncImpl(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new _(this, observer, cancel);
+                var sink = new _(observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
 
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly FirstAsync<TSource> _parent;
-
-            public _(FirstAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
-            }
-
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                base._observer.OnNext(value);
-                base._observer.OnCompleted();
-                base.Dispose();
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
-
-            public void OnCompleted()
-            {
-                if (_parent._throwOnEmpty)
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
                 }
-                else
+
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnNext(default(TSource));
+                    base._observer.OnNext(value);
                     base._observer.OnCompleted();
+                    base.Dispose();
                 }
 
-                base.Dispose();
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+                    base.Dispose();
+                }
             }
         }
 
-        class FirstAsyncImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Predicate : Producer<TSource>
         {
-            private readonly FirstAsync<TSource> _parent;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
+
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
 
-            public FirstAsyncImpl(FirstAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _parent = parent;
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                var b = false;
+                private readonly Func<TSource, bool> _predicate;
 
-                try
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    b = _parent._predicate(value);
+                    _predicate = predicate;
                 }
-                catch (Exception ex)
+
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnError(ex);
-                    base.Dispose();
-                    return;
+                    var b = false;
+
+                    try
+                    {
+                        b = _predicate(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        base._observer.OnNext(value);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
 
-                if (b)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnNext(value);
-                    base._observer.OnCompleted();
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
 
-            public void OnCompleted()
-            {
-                if (_parent._throwOnEmpty)
+                public void OnCompleted()
                 {
                     base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+                    base.Dispose();
                 }
-                else
-                {
-                    base._observer.OnNext(default(TSource));
-                    base._observer.OnCompleted();
-                }
-
-                base.Dispose();
             }
         }
     }

+ 120 - 0
Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstOrDefaultAsync.cs

@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+namespace System.Reactive.Linq.ObservableImpl
+{
+    internal static class FirstOrDefaultAsync<TSource>
+    {
+        internal sealed class Sequence : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+
+            public Sequence(IObservable<TSource> source)
+            {
+                _source = source;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                }
+
+                public void OnNext(TSource value)
+                {
+                    base._observer.OnNext(value);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(default(TSource));
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+
+        internal sealed class Predicate : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
+
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                private readonly Func<TSource, bool> _predicate;
+
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _predicate = predicate;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    var b = false;
+
+                    try
+                    {
+                        b = _predicate(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        base._observer.OnNext(value);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(default(TSource));
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+    }
+}

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/For.cs

@@ -30,7 +30,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 yield return _resultSelector(item);
         }
 
-        class _ : ConcatSink<TResult>
+        private sealed class _ : ConcatSink<TResult>
         {
             public _(IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 7 - 13
Rx.NET/Source/src/System.Reactive/Linq/Observable/ForEach.cs

@@ -8,7 +8,7 @@ namespace System.Reactive.Linq.ObservableImpl
 {
     internal sealed class ForEach<TSource>
     {
-        public class _ : IObserver<TSource>
+        public sealed class Observer : IObserver<TSource>
         {
             private readonly Action<TSource> _onNext;
             private readonly Action _done;
@@ -16,7 +16,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private Exception _exception;
             private int _stopped;
 
-            public _(Action<TSource> onNext, Action done)
+            public Observer(Action<TSource> onNext, Action done)
             {
                 _onNext = onNext;
                 _done = done;
@@ -24,10 +24,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 _stopped = 0;
             }
 
-            public Exception Error
-            {
-                get { return _exception; }
-            }
+            public Exception Error => _exception;
 
             public void OnNext(TSource value)
             {
@@ -62,7 +59,7 @@ namespace System.Reactive.Linq.ObservableImpl
             }
         }
 
-        public class ForEachImpl : IObserver<TSource>
+        public sealed class ObserverIndexed : IObserver<TSource>
         {
             private readonly Action<TSource, int> _onNext;
             private readonly Action _done;
@@ -71,19 +68,16 @@ namespace System.Reactive.Linq.ObservableImpl
             private Exception _exception;
             private int _stopped;
 
-            public ForEachImpl(Action<TSource, int> onNext, Action done)
+            public ObserverIndexed(Action<TSource, int> onNext, Action done)
             {
                 _onNext = onNext;
                 _done = done;
-                
+
                 _index = 0;
                 _stopped = 0;
             }
 
-            public Exception Error
-            {
-                get { return _exception; }
-            }
+            public Exception Error => _exception;
 
             public void OnNext(TSource value)
             {

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

@@ -190,7 +190,7 @@ namespace System.Reactive.Linq.ObservableImpl
         }
     }
 
-    abstract class EventProducer<TDelegate, TArgs> : Producer<TArgs>
+    internal abstract class EventProducer<TDelegate, TArgs> : Producer<TArgs>
     {
         private readonly IScheduler _scheduler;
         private readonly object _gate;
@@ -229,7 +229,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return connection;
         }
 
-        class Session
+        private sealed class Session
         {
             private readonly EventProducer<TDelegate, TArgs> _parent;
             private readonly Subject<TArgs> _subject;
@@ -346,7 +346,7 @@ namespace System.Reactive.Linq.ObservableImpl
         }
     }
 
-    abstract class ClassicEventProducer<TDelegate, TArgs> : EventProducer<TDelegate, TArgs>
+    internal abstract class ClassicEventProducer<TDelegate, TArgs> : EventProducer<TDelegate, TArgs>
     {
         private readonly Action<TDelegate> _addHandler;
         private readonly Action<TDelegate> _removeHandler;

+ 19 - 7
Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEventPattern.cs

@@ -15,7 +15,7 @@ namespace System.Reactive.Linq.ObservableImpl
 {
     internal sealed class FromEventPattern
     {
-        public class Impl<TDelegate, TEventArgs> : ClassicEventProducer<TDelegate, EventPattern<TEventArgs>>
+        public sealed class Impl<TDelegate, TEventArgs> : ClassicEventProducer<TDelegate, EventPattern<TEventArgs>>
         {
             private readonly Func<EventHandler<TEventArgs>, TDelegate> _conversion;
 
@@ -48,7 +48,7 @@ namespace System.Reactive.Linq.ObservableImpl
             }
         }
 
-        public class Impl<TDelegate, TSender, TEventArgs> : ClassicEventProducer<TDelegate, EventPattern<TSender, TEventArgs>>
+        public sealed class Impl<TDelegate, TSender, TEventArgs> : ClassicEventProducer<TDelegate, EventPattern<TSender, TEventArgs>>
         {
             public Impl(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
                 : base(addHandler, removeHandler, scheduler)
@@ -62,7 +62,7 @@ namespace System.Reactive.Linq.ObservableImpl
             }
         }
 
-        public class Handler<TSender, TEventArgs, TResult> : EventProducer<Delegate, TResult>
+        public sealed class Handler<TSender, TEventArgs, TResult> : EventProducer<Delegate, TResult>
         {
             private readonly object _target;
             private readonly Type _delegateType;
@@ -103,14 +103,12 @@ namespace System.Reactive.Linq.ObservableImpl
 #if HAS_WINRT
                     if (_isWinRT)
                     {
-                        var token = _addMethod.Invoke(_target, new object[] { handler });
-                        removeHandler = () => _removeMethod.Invoke(_target, new object[] { token });
+                        removeHandler = AddHandlerCoreWinRT(handler);
                     }
                     else
 #endif
                     {
-                        _addMethod.Invoke(_target, new object[] { handler });
-                        removeHandler = () => _removeMethod.Invoke(_target, new object[] { handler });
+                        removeHandler = AddHandlerCore(handler);
                     }
                 }
                 catch (TargetInvocationException tie)
@@ -130,6 +128,20 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
                 });
             }
+
+            private Action AddHandlerCore(Delegate handler)
+            {
+                _addMethod.Invoke(_target, new object[] { handler });
+                return () => _removeMethod.Invoke(_target, new object[] { handler });
+            }
+
+#if HAS_WINRT
+            private Action AddHandlerCoreWinRT(Delegate handler)
+            {
+                var token = _addMethod.Invoke(_target, new object[] { handler });
+                return () => _removeMethod.Invoke(_target, new object[] { token });
+            }
+#endif
         }
     }
 }

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

@@ -7,281 +7,347 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Generate<TState, TResult> : Producer<TResult>
+    internal static class Generate<TState, TResult>
     {
-        private readonly TState _initialState;
-        private readonly Func<TState, bool> _condition;
-        private readonly Func<TState, TState> _iterate;
-        private readonly Func<TState, TResult> _resultSelector;
-        private readonly Func<TState, DateTimeOffset> _timeSelectorA;
-        private readonly Func<TState, TimeSpan> _timeSelectorR;
-        private readonly IScheduler _scheduler;
-
-        public Generate(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, IScheduler scheduler)
+        internal sealed class NoTime : Producer<TResult>
         {
-            _initialState = initialState;
-            _condition = condition;
-            _iterate = iterate;
-            _resultSelector = resultSelector;
-            _scheduler = scheduler;
-        }
-
-        public Generate(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, DateTimeOffset> timeSelector, IScheduler scheduler)
-        {
-            _initialState = initialState;
-            _condition = condition;
-            _iterate = iterate;
-            _resultSelector = resultSelector;
-            _timeSelectorA = timeSelector;
-            _scheduler = scheduler;
-        }
-
-        public Generate(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, TimeSpan> timeSelector, IScheduler scheduler)
-        {
-            _initialState = initialState;
-            _condition = condition;
-            _iterate = iterate;
-            _resultSelector = resultSelector;
-            _timeSelectorR = timeSelector;
-            _scheduler = scheduler;
-        }
+            private readonly TState _initialState;
+            private readonly Func<TState, bool> _condition;
+            private readonly Func<TState, TState> _iterate;
+            private readonly Func<TState, TResult> _resultSelector;
+            private readonly IScheduler _scheduler;
 
-        protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_timeSelectorA != null)
-            {
-                var sink = new SelectorA(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
-            }
-            else if (_timeSelectorR != null)
+            public NoTime(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, IScheduler scheduler)
             {
-                var sink = new Delta(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _initialState = initialState;
+                _condition = condition;
+                _iterate = iterate;
+                _resultSelector = resultSelector;
+                _scheduler = scheduler;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
                 var sink = new _(this, observer, cancel);
                 setSink(sink);
                 return sink.Run();
             }
-        }
-
-        class SelectorA : Sink<TResult>
-        {
-            private readonly Generate<TState, TResult> _parent;
 
-            public SelectorA(Generate<TState, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TResult>
             {
-                _parent = parent;
-            }
-
-            private bool _first;
-            private bool _hasResult;
-            private TResult _result;
+                // CONSIDER: This sink has a parent reference that can be considered for removal.
 
-            public IDisposable Run()
-            {
-                _first = true;
-                _hasResult = false;
-                _result = default(TResult);
+                private readonly NoTime _parent;
 
-                return _parent._scheduler.Schedule(_parent._initialState, InvokeRec);
-            }
+                public _(NoTime parent, IObserver<TResult> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _parent = parent;
+                }
 
-            private IDisposable InvokeRec(IScheduler self, TState state)
-            {
-                var time = default(DateTimeOffset);
+                private TState _state;
+                private bool _first;
 
-                if (_hasResult)
-                    base._observer.OnNext(_result);
-                try
+                public IDisposable Run()
                 {
-                    if (_first)
-                        _first = false;
+                    _state = _parent._initialState;
+                    _first = true;
+
+                    var longRunning = _parent._scheduler.AsLongRunning();
+                    if (longRunning != null)
+                    {
+                        return longRunning.ScheduleLongRunning(Loop);
+                    }
                     else
-                        state = _parent._iterate(state);
-                    _hasResult = _parent._condition(state);
-                    if (_hasResult)
                     {
-                        _result = _parent._resultSelector(state);
-                        time = _parent._timeSelectorA(state);
+                        return _parent._scheduler.Schedule(LoopRec);
                     }
                 }
-                catch (Exception exception)
+
+                private void Loop(ICancelable cancel)
                 {
-                    base._observer.OnError(exception);
+                    while (!cancel.IsDisposed)
+                    {
+                        var hasResult = false;
+                        var result = default(TResult);
+                        try
+                        {
+                            if (_first)
+                            {
+                                _first = false;
+                            }
+                            else
+                            {
+                                _state = _parent._iterate(_state);
+                            }
+
+                            hasResult = _parent._condition(_state);
+
+                            if (hasResult)
+                            {
+                                result = _parent._resultSelector(_state);
+                            }
+                        }
+                        catch (Exception exception)
+                        {
+                            base._observer.OnError(exception);
+                            base.Dispose();
+                            return;
+                        }
+
+                        if (hasResult)
+                        {
+                            base._observer.OnNext(result);
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+
+                    if (!cancel.IsDisposed)
+                    {
+                        base._observer.OnCompleted();
+                    }
+
                     base.Dispose();
-                    return Disposable.Empty;
                 }
 
-                if (!_hasResult)
+                private void LoopRec(Action recurse)
                 {
-                    base._observer.OnCompleted();
-                    base.Dispose();
-                    return Disposable.Empty;
-                }
+                    var hasResult = false;
+                    var result = default(TResult);
+                    try
+                    {
+                        if (_first)
+                        {
+                            _first = false;
+                        }
+                        else
+                        {
+                            _state = _parent._iterate(_state);
+                        }
+
+                        hasResult = _parent._condition(_state);
+
+                        if (hasResult)
+                        {
+                            result = _parent._resultSelector(_state);
+                        }
+                    }
+                    catch (Exception exception)
+                    {
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                        return;
+                    }
 
-                return self.Schedule(state, time, InvokeRec);
+                    if (hasResult)
+                    {
+                        base._observer.OnNext(result);
+                        recurse();
+                    }
+                    else
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
+                }
             }
         }
 
-        class Delta : Sink<TResult>
+        internal sealed class Absolute : Producer<TResult>
         {
-            private readonly Generate<TState, TResult> _parent;
-
-            public Delta(Generate<TState, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private readonly TState _initialState;
+            private readonly Func<TState, bool> _condition;
+            private readonly Func<TState, TState> _iterate;
+            private readonly Func<TState, TResult> _resultSelector;
+            private readonly Func<TState, DateTimeOffset> _timeSelector;
+            private readonly IScheduler _scheduler;
+
+            public Absolute(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, DateTimeOffset> timeSelector, IScheduler scheduler)
             {
-                _parent = parent;
+                _initialState = initialState;
+                _condition = condition;
+                _iterate = iterate;
+                _resultSelector = resultSelector;
+                _timeSelector = timeSelector;
+                _scheduler = scheduler;
             }
 
-            private bool _first;
-            private bool _hasResult;
-            private TResult _result;
-
-            public IDisposable Run()
+            protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _first = true;
-                _hasResult = false;
-                _result = default(TResult);
-
-                return _parent._scheduler.Schedule(_parent._initialState, InvokeRec);
+                var sink = new _(this, observer, cancel);
+                setSink(sink);
+                return sink.Run();
             }
 
-            private IDisposable InvokeRec(IScheduler self, TState state)
+            private sealed class _ : Sink<TResult>
             {
-                var time = default(TimeSpan);
+                // CONSIDER: This sink has a parent reference that can be considered for removal.
+
+                private readonly Absolute _parent;
 
-                if (_hasResult)
-                    base._observer.OnNext(_result);
-                try
+                public _(Absolute parent, IObserver<TResult> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    if (_first)
-                        _first = false;
-                    else
-                        state = _parent._iterate(state);
-                    _hasResult = _parent._condition(state);
-                    if (_hasResult)
-                    {
-                        _result = _parent._resultSelector(state);
-                        time = _parent._timeSelectorR(state);
-                    }
+                    _parent = parent;
                 }
-                catch (Exception exception)
+
+                private bool _first;
+                private bool _hasResult;
+                private TResult _result;
+
+                public IDisposable Run()
                 {
-                    base._observer.OnError(exception);
-                    base.Dispose();
-                    return Disposable.Empty;
+                    _first = true;
+                    _hasResult = false;
+                    _result = default(TResult);
+
+                    return _parent._scheduler.Schedule(_parent._initialState, InvokeRec);
                 }
 
-                if (!_hasResult)
+                private IDisposable InvokeRec(IScheduler self, TState state)
                 {
-                    base._observer.OnCompleted();
-                    base.Dispose();
-                    return Disposable.Empty;
-                }
+                    var time = default(DateTimeOffset);
+
+                    if (_hasResult)
+                    {
+                        base._observer.OnNext(_result);
+                    }
+
+                    try
+                    {
+                        if (_first)
+                        {
+                            _first = false;
+                        }
+                        else
+                        {
+                            state = _parent._iterate(state);
+                        }
+
+                        _hasResult = _parent._condition(state);
+
+                        if (_hasResult)
+                        {
+                            _result = _parent._resultSelector(state);
+                            time = _parent._timeSelector(state);
+                        }
+                    }
+                    catch (Exception exception)
+                    {
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                        return Disposable.Empty;
+                    }
 
-                return self.Schedule(state, time, InvokeRec);
+                    if (!_hasResult)
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                        return Disposable.Empty;
+                    }
+
+                    return self.Schedule(state, time, InvokeRec);
+                }
             }
         }
 
-        class _ : Sink<TResult>
+        internal sealed class Relative : Producer<TResult>
         {
-            private readonly Generate<TState, TResult> _parent;
-
-            public _(Generate<TState, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private readonly TState _initialState;
+            private readonly Func<TState, bool> _condition;
+            private readonly Func<TState, TState> _iterate;
+            private readonly Func<TState, TResult> _resultSelector;
+            private readonly Func<TState, TimeSpan> _timeSelector;
+            private readonly IScheduler _scheduler;
+
+            public Relative(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, TimeSpan> timeSelector, IScheduler scheduler)
             {
-                _parent = parent;
+                _initialState = initialState;
+                _condition = condition;
+                _iterate = iterate;
+                _resultSelector = resultSelector;
+                _timeSelector = timeSelector;
+                _scheduler = scheduler;
             }
 
-            private TState _state;
-            private bool _first;
+            protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(this, observer, cancel);
+                setSink(sink);
+                return sink.Run();
+            }
 
-            public IDisposable Run()
+            private sealed class _ : Sink<TResult>
             {
-                _state = _parent._initialState;
-                _first = true;
+                // CONSIDER: This sink has a parent reference that can be considered for removal.
+
+                private readonly Relative _parent;
 
-                var longRunning = _parent._scheduler.AsLongRunning();
-                if (longRunning != null)
+                public _(Relative parent, IObserver<TResult> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    return longRunning.ScheduleLongRunning(Loop);
+                    _parent = parent;
                 }
-                else
+
+                private bool _first;
+                private bool _hasResult;
+                private TResult _result;
+
+                public IDisposable Run()
                 {
-                    return _parent._scheduler.Schedule(LoopRec);
+                    _first = true;
+                    _hasResult = false;
+                    _result = default(TResult);
+
+                    return _parent._scheduler.Schedule(_parent._initialState, InvokeRec);
                 }
-            }
 
-            private void Loop(ICancelable cancel)
-            {
-                while (!cancel.IsDisposed)
+                private IDisposable InvokeRec(IScheduler self, TState state)
                 {
-                    var hasResult = false;
-                    var result = default(TResult);
+                    var time = default(TimeSpan);
+
+                    if (_hasResult)
+                    {
+                        base._observer.OnNext(_result);
+                    }
+
                     try
                     {
                         if (_first)
+                        {
                             _first = false;
+                        }
                         else
-                            _state = _parent._iterate(_state);
-                        hasResult = _parent._condition(_state);
-                        if (hasResult)
-                            result = _parent._resultSelector(_state);
+                        {
+                            state = _parent._iterate(state);
+                        }
+
+                        _hasResult = _parent._condition(state);
+
+                        if (_hasResult)
+                        {
+                            _result = _parent._resultSelector(state);
+                            time = _parent._timeSelector(state);
+                        }
                     }
                     catch (Exception exception)
                     {
                         base._observer.OnError(exception);
                         base.Dispose();
-                        return;
+                        return Disposable.Empty;
                     }
 
-                    if (hasResult)
-                        base._observer.OnNext(result);
-                    else
-                        break;
-                }
-
-                if (!cancel.IsDisposed)
-                    base._observer.OnCompleted();
-
-                base.Dispose();
-            }
-
-            private void LoopRec(Action recurse)
-            {
-                var hasResult = false;
-                var result = default(TResult);
-                try
-                {
-                    if (_first)
-                        _first = false;
-                    else
-                        _state = _parent._iterate(_state);
-                    hasResult = _parent._condition(_state);
-                    if (hasResult)
-                        result = _parent._resultSelector(_state);
-                }
-                catch (Exception exception)
-                {
-                    base._observer.OnError(exception);
-                    base.Dispose();
-                    return;
-                }
+                    if (!_hasResult)
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                        return Disposable.Empty;
+                    }
 
-                if (hasResult)
-                {
-                    base._observer.OnNext(result);
-                    recurse();
-                }
-                else
-                {
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                    return self.Schedule(state, time, InvokeRec);
                 }
             }
         }

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

@@ -75,15 +75,9 @@ namespace System.Reactive.Linq.ObservableImpl
             return false;
         }
 
-        public TSource Current
-        {
-            get { return _current; }
-        }
+        public TSource Current => _current;
 
-        object Collections.IEnumerator.Current
-        {
-            get { return _current; }
-        }
+        object Collections.IEnumerator.Current => _current;
 
         public void Dispose()
         {

+ 27 - 25
Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupBy.cs

@@ -25,48 +25,52 @@ namespace System.Reactive.Linq.ObservableImpl
             _comparer = comparer;
         }
 
-        private CompositeDisposable _groupDisposable;
-        private RefCountDisposable _refCountDisposable;
-
         protected override IDisposable Run(IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            _groupDisposable = new CompositeDisposable();
-            _refCountDisposable = new RefCountDisposable(_groupDisposable);
-
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            _groupDisposable.Add(_source.SubscribeSafe(sink));
-
-            return _refCountDisposable;
+            return sink.Run(_source);
         }
 
-        class _ : Sink<IGroupedObservable<TKey, TElement>>, IObserver<TSource>
+        private sealed class _ : Sink<IGroupedObservable<TKey, TElement>>, IObserver<TSource>
         {
-            private readonly GroupBy<TSource, TKey, TElement> _parent;
-            private readonly Dictionary<TKey, ISubject<TElement>> _map;
-            private ISubject<TElement> _null;
+            private readonly Func<TSource, TKey> _keySelector;
+            private readonly Func<TSource, TElement> _elementSelector;
+            private readonly Dictionary<TKey, Subject<TElement>> _map;
+
+            private RefCountDisposable _refCountDisposable;
+            private Subject<TElement> _null;
 
             public _(GroupBy<TSource, TKey, TElement> parent, IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _keySelector = parent._keySelector;
+                _elementSelector = parent._elementSelector;
 
-                if (_parent._capacity.HasValue)
+                if (parent._capacity.HasValue)
                 {
-                    _map = new Dictionary<TKey, ISubject<TElement>>(_parent._capacity.Value, _parent._comparer);
+                    _map = new Dictionary<TKey, Subject<TElement>>(parent._capacity.Value, parent._comparer);
                 }
                 else
                 {
-                    _map = new Dictionary<TKey, ISubject<TElement>>(_parent._comparer);
+                    _map = new Dictionary<TKey, Subject<TElement>>(parent._comparer);
                 }
             }
 
+            public IDisposable Run(IObservable<TSource> source)
+            {
+                var sourceSubscription = new SingleAssignmentDisposable();
+                _refCountDisposable = new RefCountDisposable(sourceSubscription);
+                sourceSubscription.Disposable = source.SubscribeSafe(this);
+                return _refCountDisposable;
+            }
+
             public void OnNext(TSource value)
             {
                 var key = default(TKey);
                 try
                 {
-                    key = _parent._keySelector(value);
+                    key = _keySelector(value);
                 }
                 catch (Exception exception)
                 {
@@ -75,7 +79,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
 
                 var fireNewMapEntry = false;
-                var writer = default(ISubject<TElement>);
+                var writer = default(Subject<TElement>);
                 try
                 {
                     //
@@ -124,14 +128,14 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 if (fireNewMapEntry)
                 {
-                    var group = new GroupedObservable<TKey, TElement>(key, writer, _parent._refCountDisposable);
+                    var group = new GroupedObservable<TKey, TElement>(key, writer, _refCountDisposable);
                     _observer.OnNext(group);
                 }
 
                 var element = default(TElement);
                 try
                 {
-                    element = _parent._elementSelector(value);
+                    element = _elementSelector(value);
                 }
                 catch (Exception exception)
                 {
@@ -149,8 +153,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public void OnCompleted()
             {
-                if (_null != null)
-                    _null.OnCompleted();
+                _null?.OnCompleted();
 
                 foreach (var w in _map.Values)
                     w.OnCompleted();
@@ -161,8 +164,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
             private void Error(Exception exception)
             {
-                if (_null != null)
-                    _null.OnError(exception);
+                _null?.OnError(exception);
 
                 foreach (var w in _map.Values)
                     w.OnError(exception);

+ 40 - 42
Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupByUntil.cs

@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the Apache 2.0 License.
 // See the LICENSE file in the project root for more information. 
 
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
 using System.Reactive.Disposables;
@@ -28,34 +29,42 @@ namespace System.Reactive.Linq.ObservableImpl
             _comparer = comparer;
         }
 
-        private CompositeDisposable _groupDisposable;
-        private RefCountDisposable _refCountDisposable;
-
         protected override IDisposable Run(IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            _groupDisposable = new CompositeDisposable();
-            _refCountDisposable = new RefCountDisposable(_groupDisposable);
-
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            _groupDisposable.Add(_source.SubscribeSafe(sink));
-
-            return _refCountDisposable;
+            return sink.Run(_source);
         }
 
-        class _ : Sink<IGroupedObservable<TKey, TElement>>, IObserver<TSource>
+        private sealed class _ : Sink<IGroupedObservable<TKey, TElement>>, IObserver<TSource>
         {
-            private readonly GroupByUntil<TSource, TKey, TElement, TDuration> _parent;
+            private readonly object _nullGate = new object();
+            private readonly CompositeDisposable _groupDisposable = new CompositeDisposable();
+            private readonly RefCountDisposable _refCountDisposable;
             private readonly Map<TKey, ISubject<TElement>> _map;
+
+            private readonly Func<TSource, TKey> _keySelector;
+            private readonly Func<TSource, TElement> _elementSelector;
+            private readonly Func<IGroupedObservable<TKey, TElement>, IObservable<TDuration>> _durationSelector;
+
             private ISubject<TElement> _null;
-            private object _nullGate;
 
             public _(GroupByUntil<TSource, TKey, TElement, TDuration> parent, IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _map = new Map<TKey, ISubject<TElement>>(_parent._capacity, _parent._comparer);
-                _nullGate = new object();
+                _refCountDisposable = new RefCountDisposable(_groupDisposable);
+                _map = new Map<TKey, ISubject<TElement>>(parent._capacity, parent._comparer);
+
+                _keySelector = parent._keySelector;
+                _elementSelector = parent._elementSelector;
+                _durationSelector = parent._durationSelector;
+            }
+
+            public IDisposable Run(IObservable<TSource> source)
+            {
+                _groupDisposable.Add(source.SubscribeSafe(this));
+
+                return _refCountDisposable;
             }
 
             private ISubject<TElement> NewSubject()
@@ -70,7 +79,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 var key = default(TKey);
                 try
                 {
-                    key = _parent._keySelector(value);
+                    key = _keySelector(value);
                 }
                 catch (Exception exception)
                 {
@@ -116,14 +125,14 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 if (fireNewMapEntry)
                 {
-                    var group = new GroupedObservable<TKey, TElement>(key, writer, _parent._refCountDisposable);
+                    var group = new GroupedObservable<TKey, TElement>(key, writer, _refCountDisposable);
 
                     var duration = default(IObservable<TDuration>);
 
                     var durationGroup = new GroupedObservable<TKey, TElement>(key, writer);
                     try
                     {
-                        duration = _parent._durationSelector(durationGroup);
+                        duration = _durationSelector(durationGroup);
                     }
                     catch (Exception exception)
                     {
@@ -135,14 +144,14 @@ namespace System.Reactive.Linq.ObservableImpl
                         base._observer.OnNext(group);
 
                     var md = new SingleAssignmentDisposable();
-                    _parent._groupDisposable.Add(md);
-                    md.Disposable = duration.SubscribeSafe(new Delta(this, key, writer, md));
+                    _groupDisposable.Add(md);
+                    md.Disposable = duration.SubscribeSafe(new DurationObserver(this, key, writer, md));
                 }
 
                 var element = default(TElement);
                 try
                 {
-                    element = _parent._elementSelector(value);
+                    element = _elementSelector(value);
                 }
                 catch (Exception exception)
                 {
@@ -171,14 +180,14 @@ namespace System.Reactive.Linq.ObservableImpl
                 writer.OnNext(element);
             }
 
-            class Delta : IObserver<TDuration>
+            private sealed class DurationObserver : IObserver<TDuration>
             {
                 private readonly _ _parent;
                 private readonly TKey _key;
                 private readonly ISubject<TElement> _writer;
                 private readonly IDisposable _self;
 
-                public Delta(_ parent, TKey key, ISubject<TElement> writer, IDisposable self)
+                public DurationObserver(_ parent, TKey key, ISubject<TElement> writer, IDisposable self)
                 {
                     _parent = parent;
                     _key = key;
@@ -218,7 +227,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         }
                     }
 
-                    _parent._parent._groupDisposable.Remove(_self);
+                    _parent._groupDisposable.Remove(_self);
                 }
             }
 
@@ -238,8 +247,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 lock (_nullGate)
                     @null = _null;
 
-                if (@null != null)
-                    @null.OnCompleted();
+                @null?.OnCompleted();
 
                 foreach (var w in _map.Values)
                     w.OnCompleted();
@@ -261,8 +269,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 lock (_nullGate)
                     @null = _null;
 
-                if (@null != null)
-                    @null.OnError(exception);
+                @null?.OnError(exception);
 
                 foreach (var w in _map.Values)
                     w.OnError(exception);
@@ -286,22 +293,19 @@ namespace System.Reactive.Linq.ObservableImpl
         // compromise.
         private const int DEFAULT_CONCURRENCY_MULTIPLIER = 4;
 
-        private static int DefaultConcurrencyLevel
-        {
-            get { return DEFAULT_CONCURRENCY_MULTIPLIER * Environment.ProcessorCount; }
-        }
+        private static int DefaultConcurrencyLevel => DEFAULT_CONCURRENCY_MULTIPLIER * Environment.ProcessorCount;
 
-        private readonly System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> _map;
+        private readonly ConcurrentDictionary<TKey, TValue> _map;
 
         public Map(int? capacity, IEqualityComparer<TKey> comparer)
         {
             if (capacity.HasValue)
             {
-                _map = new System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>(DefaultConcurrencyLevel, capacity.Value, comparer);
+                _map = new ConcurrentDictionary<TKey, TValue>(DefaultConcurrencyLevel, capacity.Value, comparer);
             }
             else
             {
-                _map = new System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>(comparer);
+                _map = new ConcurrentDictionary<TKey, TValue>(comparer);
             }
         }
 
@@ -334,13 +338,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return value;
         }
 
-        public IEnumerable<TValue> Values
-        {
-            get
-            {
-                return _map.Values.ToArray();
-            }
-        }
+        public IEnumerable<TValue> Values => _map.Values.ToArray();
 
         public bool Remove(TKey key)
         {

+ 32 - 31
Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupJoin.cs

@@ -29,52 +29,53 @@ namespace System.Reactive.Linq.ObservableImpl
         {
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TResult>
+        private sealed class _ : Sink<TResult>
         {
-            private readonly GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult> _parent;
+            private readonly object _gate = new object();
+            private readonly CompositeDisposable _group = new CompositeDisposable();
+            private readonly RefCountDisposable _refCount;
+            private readonly SortedDictionary<int, IObserver<TRight>> _leftMap = new SortedDictionary<int, IObserver<TRight>>();
+            private readonly SortedDictionary<int, TRight> _rightMap = new SortedDictionary<int, TRight>();
+
+            private readonly Func<TLeft, IObservable<TLeftDuration>> _leftDurationSelector;
+            private readonly Func<TRight, IObservable<TRightDuration>> _rightDurationSelector;
+            private readonly Func<TLeft, IObservable<TRight>, TResult> _resultSelector;
 
             public _(GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-            }
+                _refCount = new RefCountDisposable(_group);
+                _leftMap = new SortedDictionary<int, IObserver<TRight>>();
+                _rightMap = new SortedDictionary<int, TRight>();
 
-            private object _gate;
-            private CompositeDisposable _group;
-            private RefCountDisposable _refCount;
+                _leftDurationSelector = parent._leftDurationSelector;
+                _rightDurationSelector = parent._rightDurationSelector;
+                _resultSelector = parent._resultSelector;
+            }
 
             private int _leftID;
-            private SortedDictionary<int, IObserver<TRight>> _leftMap;
-
             private int _rightID;
-            private SortedDictionary<int, TRight> _rightMap;
 
-            public IDisposable Run()
+            public IDisposable Run(GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult> parent)
             {
-                _gate = new object();
-                _group = new CompositeDisposable();
-                _refCount = new RefCountDisposable(_group);
-
                 var leftSubscription = new SingleAssignmentDisposable();
                 _group.Add(leftSubscription);
                 _leftID = 0;
-                _leftMap = new SortedDictionary<int, IObserver<TRight>>();
 
                 var rightSubscription = new SingleAssignmentDisposable();
                 _group.Add(rightSubscription);
                 _rightID = 0;
-                _rightMap = new SortedDictionary<int, TRight>();
 
-                leftSubscription.Disposable = _parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription));
-                rightSubscription.Disposable = _parent._right.SubscribeSafe(new RightObserver(this, rightSubscription));
+                leftSubscription.Disposable = parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription));
+                rightSubscription.Disposable = parent._right.SubscribeSafe(new RightObserver(this, rightSubscription));
 
                 return _refCount;
             }
 
-            class LeftObserver : IObserver<TLeft>
+            private sealed class LeftObserver : IObserver<TLeft>
             {
                 private readonly _ _parent;
                 private readonly IDisposable _self;
@@ -119,7 +120,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var duration = default(IObservable<TLeftDuration>);
                     try
                     {
-                        duration = _parent._parent._leftDurationSelector(value);
+                        duration = _parent._leftDurationSelector(value);
                     }
                     catch (Exception exception)
                     {
@@ -128,12 +129,12 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
 
                     // BREAKING CHANGE v2 > v1.x - The duration sequence is subscribed to before the result sequence is evaluated.
-                    md.Disposable = duration.SubscribeSafe(new Delta(this, id, s, md));
+                    md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, s, md));
 
                     var result = default(TResult);
                     try
                     {
-                        result = _parent._parent._resultSelector(value, window);
+                        result = _parent._resultSelector(value, window);
                     }
                     catch (Exception exception)
                     {
@@ -155,14 +156,14 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
                 }
 
-                class Delta : IObserver<TLeftDuration>
+                private sealed class DurationObserver : IObserver<TLeftDuration>
                 {
                     private readonly LeftObserver _parent;
                     private readonly int _id;
                     private readonly IObserver<TRight> _group;
                     private readonly IDisposable _self;
 
-                    public Delta(LeftObserver parent, int id, IObserver<TRight> group, IDisposable self)
+                    public DurationObserver(LeftObserver parent, int id, IObserver<TRight> group, IDisposable self)
                     {
                         _parent = parent;
                         _id = id;
@@ -212,7 +213,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class RightObserver : IObserver<TRight>
+            private sealed class RightObserver : IObserver<TRight>
             {
                 private readonly _ _parent;
                 private readonly IDisposable _self;
@@ -250,7 +251,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var duration = default(IObservable<TRightDuration>);
                     try
                     {
-                        duration = _parent._parent._rightDurationSelector(value);
+                        duration = _parent._rightDurationSelector(value);
                     }
                     catch (Exception exception)
                     {
@@ -258,7 +259,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         return;
                     }
 
-                    md.Disposable = duration.SubscribeSafe(new Delta(this, id, md));
+                    md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, md));
 
                     lock (_parent._gate)
                     {
@@ -272,13 +273,13 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
                 }
 
-                class Delta : IObserver<TRightDuration>
+                private sealed class DurationObserver : IObserver<TRightDuration>
                 {
                     private readonly RightObserver _parent;
                     private readonly int _id;
                     private readonly IDisposable _self;
 
-                    public Delta(RightObserver parent, int id, IDisposable self)
+                    public DurationObserver(RightObserver parent, int id, IDisposable self)
                     {
                         _parent = parent;
                         _id = id;

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

@@ -19,10 +19,7 @@ namespace System.Reactive.Linq.ObservableImpl
             _elseSource = elseSource;
         }
 
-        public IObservable<TResult> Eval()
-        {
-            return _condition() ? _thenSource : _elseSource;
-        }
+        public IObservable<TResult> Eval() => _condition() ? _thenSource : _elseSource;
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
@@ -31,7 +28,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return sink.Run();
         }
 
-        class _ : Sink<TResult>, IObserver<TResult>
+        private sealed class _ : Sink<TResult>, IObserver<TResult>
         {
             private readonly If<TResult> _parent;
 

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/IgnoreElements.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/IsEmpty.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<bool>, IObserver<TSource>
+        private sealed class _ : Sink<bool>, IObserver<TSource>
         {
             public _(IObserver<bool> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 29 - 30
Rx.NET/Source/src/System.Reactive/Linq/Observable/Join.cs

@@ -28,54 +28,53 @@ namespace System.Reactive.Linq.ObservableImpl
         {
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TResult>
+        private sealed class _ : Sink<TResult>
         {
-            private readonly Join<TLeft, TRight, TLeftDuration, TRightDuration, TResult> _parent;
+            private readonly object _gate = new object();
+            private readonly CompositeDisposable _group = new CompositeDisposable();
+            private readonly SortedDictionary<int, TLeft> _leftMap = new SortedDictionary<int, TLeft>();
+            private readonly SortedDictionary<int, TRight> _rightMap = new SortedDictionary<int, TRight>();
+
+            private readonly Func<TLeft, IObservable<TLeftDuration>> _leftDurationSelector;
+            private readonly Func<TRight, IObservable<TRightDuration>> _rightDurationSelector;
+            private readonly Func<TLeft, TRight, TResult> _resultSelector;
 
             public _(Join<TLeft, TRight, TLeftDuration, TRightDuration, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _leftDurationSelector = parent._leftDurationSelector;
+                _rightDurationSelector = parent._rightDurationSelector;
+                _resultSelector = parent._resultSelector;
             }
 
-            private object _gate;
-            private CompositeDisposable _group;
-
             private bool _leftDone;
             private int _leftID;
-            private SortedDictionary<int, TLeft> _leftMap;
-                   
+
             private bool _rightDone;
             private int _rightID;
-            private SortedDictionary<int, TRight> _rightMap;
 
-            public IDisposable Run()
+            public IDisposable Run(Join<TLeft, TRight, TLeftDuration, TRightDuration, TResult> parent)
             {
-                _gate = new object();
-                _group = new CompositeDisposable();
-                
                 var leftSubscription = new SingleAssignmentDisposable();
                 _group.Add(leftSubscription);
                 _leftDone = false;
                 _leftID = 0;
-                _leftMap = new SortedDictionary<int, TLeft>();
 
                 var rightSubscription = new SingleAssignmentDisposable();
                 _group.Add(rightSubscription);
                 _rightDone = false;
                 _rightID = 0;
-                _rightMap = new SortedDictionary<int, TRight>();
 
-                leftSubscription.Disposable = _parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription));
-                rightSubscription.Disposable = _parent._right.SubscribeSafe(new RightObserver(this, rightSubscription));
+                leftSubscription.Disposable = parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription));
+                rightSubscription.Disposable = parent._right.SubscribeSafe(new RightObserver(this, rightSubscription));
 
                 return _group;
             }
 
-            class LeftObserver : IObserver<TLeft>
+            private sealed class LeftObserver : IObserver<TLeft>
             {
                 private readonly _ _parent;
                 private readonly IDisposable _self;
@@ -117,7 +116,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var duration = default(IObservable<TLeftDuration>);
                     try
                     {
-                        duration = _parent._parent._leftDurationSelector(value);
+                        duration = _parent._leftDurationSelector(value);
                     }
                     catch (Exception exception)
                     {
@@ -126,7 +125,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         return;
                     }
 
-                    md.Disposable = duration.SubscribeSafe(new Delta(this, id, md));
+                    md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, md));
 
                     lock (_parent._gate)
                     {
@@ -137,7 +136,7 @@ namespace System.Reactive.Linq.ObservableImpl
                                 var result = default(TResult);
                                 try
                                 {
-                                    result = _parent._parent._resultSelector(value, rightValue.Value);
+                                    result = _parent._resultSelector(value, rightValue.Value);
                                 }
                                 catch (Exception exception)
                                 {
@@ -152,13 +151,13 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
                 }
 
-                class Delta : IObserver<TLeftDuration>
+                private sealed class DurationObserver : IObserver<TLeftDuration>
                 {
                     private readonly LeftObserver _parent;
                     private readonly int _id;
                     private readonly IDisposable _self;
 
-                    public Delta(LeftObserver parent, int id, IDisposable self)
+                    public DurationObserver(LeftObserver parent, int id, IDisposable self)
                     {
                         _parent = parent;
                         _id = id;
@@ -208,7 +207,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class RightObserver : IObserver<TRight>
+            private sealed class RightObserver : IObserver<TRight>
             {
                 private readonly _ _parent;
                 private readonly IDisposable _self;
@@ -250,7 +249,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var duration = default(IObservable<TRightDuration>);
                     try
                     {
-                        duration = _parent._parent._rightDurationSelector(value);
+                        duration = _parent._rightDurationSelector(value);
                     }
                     catch (Exception exception)
                     {
@@ -259,7 +258,7 @@ namespace System.Reactive.Linq.ObservableImpl
                         return;
                     }
 
-                    md.Disposable = duration.SubscribeSafe(new Delta(this, id, md));
+                    md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, md));
 
                     lock (_parent._gate)
                     {
@@ -270,7 +269,7 @@ namespace System.Reactive.Linq.ObservableImpl
                                 var result = default(TResult);
                                 try
                                 {
-                                    result = _parent._parent._resultSelector(leftValue.Value, value);
+                                    result = _parent._resultSelector(leftValue.Value, value);
                                 }
                                 catch (Exception exception)
                                 {
@@ -285,13 +284,13 @@ namespace System.Reactive.Linq.ObservableImpl
                     }
                 }
 
-                class Delta : IObserver<TRightDuration>
+                private sealed class DurationObserver : IObserver<TRightDuration>
                 {
                     private readonly RightObserver _parent;
                     private readonly int _id;
                     private readonly IDisposable _self;
 
-                    public Delta(RightObserver parent, int id, IDisposable self)
+                    public DurationObserver(RightObserver parent, int id, IDisposable self)
                     {
                         _parent = parent;
                         _id = id;

+ 95 - 89
Rx.NET/Source/src/System.Reactive/Linq/Observable/LastAsync.cs

@@ -4,134 +4,140 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class LastAsync<TSource> : Producer<TSource>
+    internal static class LastAsync<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-        private readonly bool _throwOnEmpty;
-
-        public LastAsync(IObservable<TSource> source, Func<TSource, bool> predicate, bool throwOnEmpty)
+        internal sealed class Sequence : Producer<TSource>
         {
-            _source = source;
-            _predicate = predicate;
-            _throwOnEmpty = throwOnEmpty;
-        }
+            private readonly IObservable<TSource> _source;
 
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate != null)
+            public Sequence(IObservable<TSource> source)
             {
-                var sink = new LastAsyncImpl(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new _(this, observer, cancel);
+                var sink = new _(observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
-
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly LastAsync<TSource> _parent;
-            private TSource _value;
-            private bool _seenValue;
-
-            public _(LastAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
-
-                _value = default(TSource);
-                _seenValue = false;
-            }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _value = value;
-                _seenValue = true;
-            }
+                private TSource _value;
+                private bool _seenValue;
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _value = default(TSource);
+                    _seenValue = false;
+                }
 
-            public void OnCompleted()
-            {
-                if (!_seenValue && _parent._throwOnEmpty)
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+                    _value = value;
+                    _seenValue = true;
                 }
-                else
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnNext(_value);
-                    base._observer.OnCompleted();
+                    base._observer.OnError(error);
+                    base.Dispose();
                 }
 
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    if (!_seenValue)
+                    {
+                        base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+                    }
+                    else
+                    {
+                        base._observer.OnNext(_value);
+                        base._observer.OnCompleted();
+                    }
+
+                    base.Dispose();
+                }
             }
         }
 
-        class LastAsyncImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Predicate : Producer<TSource>
         {
-            private readonly LastAsync<TSource> _parent;
-            private TSource _value;
-            private bool _seenValue;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
 
-            public LastAsyncImpl(LastAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
             {
-                _parent = parent;
+                _source = source;
+                _predicate = predicate;
+            }
 
-                _value = default(TSource);
-                _seenValue = false;
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                var b = false;
+                private readonly Func<TSource, bool> _predicate;
+                private TSource _value;
+                private bool _seenValue;
 
-                try
-                {
-                    b = _parent._predicate(value);
-                }
-                catch (Exception ex)
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnError(ex);
-                    base.Dispose();
-                    return;
+                    _predicate = predicate;
+
+                    _value = default(TSource);
+                    _seenValue = false;
                 }
 
-                if (b)
+                public void OnNext(TSource value)
                 {
-                    _value = value;
-                    _seenValue = true;
+                    var b = false;
+
+                    try
+                    {
+                        b = _predicate(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        _value = value;
+                        _seenValue = true;
+                    }
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
 
-            public void OnCompleted()
-            {
-                if (!_seenValue && _parent._throwOnEmpty)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+                    base._observer.OnError(error);
+                    base.Dispose();
                 }
-                else
+
+                public void OnCompleted()
                 {
-                    base._observer.OnNext(_value);
-                    base._observer.OnCompleted();
-                }
+                    if (!_seenValue)
+                    {
+                        base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+                    }
+                    else
+                    {
+                        base._observer.OnNext(_value);
+                        base._observer.OnCompleted();
+                    }
 
-                base.Dispose();
+                    base.Dispose();
+                }
             }
         }
     }

+ 122 - 0
Rx.NET/Source/src/System.Reactive/Linq/Observable/LastOrDefaultAsync.cs

@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+namespace System.Reactive.Linq.ObservableImpl
+{
+    internal static class LastOrDefaultAsync<TSource>
+    {
+        internal sealed class Sequence : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+
+            public Sequence(IObservable<TSource> source)
+            {
+                _source = source;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                private TSource _value;
+
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _value = default(TSource);
+                }
+
+                public void OnNext(TSource value)
+                {
+                    _value = value;
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_value);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+
+        internal sealed class Predicate : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
+
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                private readonly Func<TSource, bool> _predicate;
+                private TSource _value;
+
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _predicate = predicate;
+
+                    _value = default(TSource);
+                }
+
+                public void OnNext(TSource value)
+                {
+                    var b = false;
+
+                    try
+                    {
+                        b = _predicate(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        _value = value;
+                    }
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_value);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+    }
+}

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/Latest.cs

@@ -18,7 +18,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return new _(subscription);
         }
 
-        class _ : PushToPullSink<TSource, TSource>
+        private sealed class _ : PushToPullSink<TSource, TSource>
         {
             private readonly object _gate;
             private readonly SemaphoreSlim _semaphore;

+ 83 - 75
Rx.NET/Source/src/System.Reactive/Linq/Observable/LongCount.cs

@@ -4,118 +4,126 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class LongCount<TSource> : Producer<long>
+    internal static class LongCount<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-
-        public LongCount(IObservable<TSource> source)
+        internal sealed class All : Producer<long>
         {
-            _source = source;
-        }
+            private readonly IObservable<TSource> _source;
 
-        public LongCount(IObservable<TSource> source, Func<TSource, bool> predicate)
-        {
-            _source = source;
-            _predicate = predicate;
-        }
-
-        protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate == null)
+            public All(IObservable<TSource> source)
             {
-                var sink = new _(observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
             }
-            else
+
+            protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new LongCountImpl(this, observer, cancel);
+                var sink = new _(observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
-
-        class _ : Sink<long>, IObserver<TSource>
-        {
-            private long _count;
 
-            public _(IObserver<long> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<long>, IObserver<TSource>
             {
-                _count = 0L;
-            }
+                private long _count;
 
-            public void OnNext(TSource value)
-            {
-                try
+                public _(IObserver<long> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    checked
+                    _count = 0L;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    try
                     {
-                        _count++;
+                        checked
+                        {
+                            _count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
                     }
                 }
-                catch (Exception ex)
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(ex);
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
 
-            public void OnCompleted()
-            {
-                base._observer.OnNext(_count);
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_count);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class LongCountImpl : Sink<long>, IObserver<TSource>
+        internal sealed class Predicate : Producer<long>
         {
-            private readonly LongCount<TSource> _parent;
-            private long _count;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
 
-            public LongCountImpl(LongCount<TSource> parent, IObserver<long> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
             {
-                _parent = parent;
-                _count = 0L;
+                _source = source;
+                _predicate = predicate;
             }
 
-            public void OnNext(TSource value)
+            protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                try
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<long>, IObserver<TSource>
+            {
+                private readonly Func<TSource, bool> _predicate;
+                private long _count;
+
+                public _(Func<TSource, bool> predicate, IObserver<long> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _predicate = predicate;
+                    _count = 0L;
+                }
+
+                public void OnNext(TSource value)
                 {
-                    checked
+                    try
                     {
-                        if (_parent._predicate(value))
-                            _count++;
+                        checked
+                        {
+                            if (_predicate(value))
+                            {
+                                _count++;
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
                     }
                 }
-                catch (Exception ex)
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(ex);
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
-
-            public void OnCompleted()
-            {
-                base._observer.OnNext(_count);
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_count);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

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

@@ -13,10 +13,7 @@ namespace System.Reactive.Linq.ObservableImpl
             _source = source;
         }
 
-        public IObservable<TSource> Dematerialize()
-        {
-            return _source.AsObservable();
-        }
+        public IObservable<TSource> Dematerialize() => _source.AsObservable();
 
         protected override IDisposable Run(IObserver<Notification<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
@@ -25,7 +22,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<Notification<TSource>>, IObserver<TSource>
+        private sealed class _ : Sink<Notification<TSource>>, IObserver<TSource>
         {
             public _(IObserver<Notification<TSource>> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 22 - 22
Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs

@@ -22,28 +22,28 @@ namespace System.Reactive.Linq.ObservableImpl
             // LINQ to Objects makes this distinction in order to make [Max|Max] of an empty collection of reference type objects equal to null.
             if (default(TSource) == null)
             {
-                var sink = new _(this, observer, cancel);
+                var sink = new Null(_comparer, observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
             else
             {
-                var sink = new Delta(this, observer, cancel);
+                var sink = new NonNull(_comparer, observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
         }
 
-        class Delta : Sink<TSource>, IObserver<TSource>
+        private sealed class NonNull : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Max<TSource> _parent;
+            private readonly IComparer<TSource> _comparer;
             private bool _hasValue;
             private TSource _lastValue;
 
-            public Delta(Max<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public NonNull(IComparer<TSource> comparer, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _comparer = comparer;
 
                 _hasValue = false;
                 _lastValue = default(TSource);
@@ -57,7 +57,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                     try
                     {
-                        comparison = _parent._comparer.Compare(value, _lastValue);
+                        comparison = _comparer.Compare(value, _lastValue);
                     }
                     catch (Exception ex)
                     {
@@ -100,15 +100,15 @@ namespace System.Reactive.Linq.ObservableImpl
             }
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class Null : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Max<TSource> _parent;
+            private readonly IComparer<TSource> _comparer;
             private TSource _lastValue;
 
-            public _(Max<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public Null(IComparer<TSource> comparer, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _comparer = comparer;
 
                 _lastValue = default(TSource);
             }
@@ -127,7 +127,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                         try
                         {
-                            comparison = _parent._comparer.Compare(value, _lastValue);
+                            comparison = _comparer.Compare(value, _lastValue);
                         }
                         catch (Exception ex)
                         {
@@ -175,7 +175,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double>, IObserver<double>
+        private sealed class _ : Sink<double>, IObserver<double>
         {
             private bool _hasValue;
             private double _lastValue;
@@ -242,7 +242,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float>, IObserver<float>
+        private sealed class _ : Sink<float>, IObserver<float>
         {
             private bool _hasValue;
             private float _lastValue;
@@ -309,7 +309,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal>, IObserver<decimal>
+        private sealed class _ : Sink<decimal>, IObserver<decimal>
         {
             private bool _hasValue;
             private decimal _lastValue;
@@ -376,7 +376,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<int>, IObserver<int>
+        private sealed class _ : Sink<int>, IObserver<int>
         {
             private bool _hasValue;
             private int _lastValue;
@@ -443,7 +443,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<long>, IObserver<long>
+        private sealed class _ : Sink<long>, IObserver<long>
         {
             private bool _hasValue;
             private long _lastValue;
@@ -510,7 +510,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double?>, IObserver<double?>
+        private sealed class _ : Sink<double?>, IObserver<double?>
         {
             private double? _lastValue;
 
@@ -569,7 +569,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float?>, IObserver<float?>
+        private sealed class _ : Sink<float?>, IObserver<float?>
         {
             private float? _lastValue;
 
@@ -628,7 +628,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal?>, IObserver<decimal?>
+        private sealed class _ : Sink<decimal?>, IObserver<decimal?>
         {
             private decimal? _lastValue;
 
@@ -687,7 +687,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<int?>, IObserver<int?>
+        private sealed class _ : Sink<int?>, IObserver<int?>
         {
             private int? _lastValue;
 
@@ -746,7 +746,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<long?>, IObserver<long?>
+        private sealed class _ : Sink<long?>, IObserver<long?>
         {
             private long? _lastValue;
 

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/MaxBy.cs

@@ -26,7 +26,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<IList<TSource>>, IObserver<TSource>
+        private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
         {
             private readonly MaxBy<TSource, TKey> _parent;
             private bool _hasValue;

+ 259 - 254
Rx.NET/Source/src/System.Reactive/Linq/Observable/Merge.cs

@@ -9,285 +9,276 @@ using System.Threading.Tasks;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Merge<TSource> : Producer<TSource>
+    internal static class Merge<TSource>
     {
-        private readonly IObservable<IObservable<TSource>> _sources;
-        private readonly IObservable<Task<TSource>> _sourcesT;
-        private readonly int _maxConcurrent;
-
-        public Merge(IObservable<IObservable<TSource>> sources)
-        {
-            _sources = sources;
-        }
-
-        public Merge(IObservable<IObservable<TSource>> sources, int maxConcurrent)
+        internal sealed class ObservablesMaxConcurrency : Producer<TSource>
         {
-            _sources = sources;
-            _maxConcurrent = maxConcurrent;
-        }
+            private readonly IObservable<IObservable<TSource>> _sources;
+            private readonly int _maxConcurrent;
 
-        public Merge(IObservable<Task<TSource>> sources)
-        {
-            _sourcesT = sources;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_maxConcurrent > 0)
-            {
-                var sink = new MergeConcurrent(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
-            }
-            else if (_sourcesT != null)
+            public ObservablesMaxConcurrency(IObservable<IObservable<TSource>> sources, int maxConcurrent)
             {
-                var sink = new MergeImpl(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _sources = sources;
+                _maxConcurrent = maxConcurrent;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new _(this, observer, cancel);
+                var sink = new _(_maxConcurrent, observer, cancel);
                 setSink(sink);
-                return sink.Run();
+                return sink.Run(this);
             }
-        }
-
-        class _ : Sink<TSource>, IObserver<IObservable<TSource>>
-        {
-            private readonly Merge<TSource> _parent;
 
-            public _(Merge<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TSource>, IObserver<IObservable<TSource>>
             {
-                _parent = parent;
-            }
+                private readonly int _maxConcurrent;
 
-            private object _gate;
-            private bool _isStopped;
-            private CompositeDisposable _group;
-            private SingleAssignmentDisposable _sourceSubscription;
+                public _(int maxConcurrent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _maxConcurrent = maxConcurrent;
+                }
 
-            public IDisposable Run()
-            {
-                _gate = new object();
-                _isStopped = false;
-                _group = new CompositeDisposable();
+                private object _gate;
+                private Queue<IObservable<TSource>> _q;
+                private bool _isStopped;
+                private SingleAssignmentDisposable _sourceSubscription;
+                private CompositeDisposable _group;
+                private int _activeCount = 0;
 
-                _sourceSubscription = new SingleAssignmentDisposable();
-                _group.Add(_sourceSubscription);
-                _sourceSubscription.Disposable = _parent._sources.SubscribeSafe(this);
+                public IDisposable Run(ObservablesMaxConcurrency parent)
+                {
+                    _gate = new object();
+                    _q = new Queue<IObservable<TSource>>();
+                    _isStopped = false;
+                    _activeCount = 0;
 
-                return _group;
-            }
+                    _group = new CompositeDisposable();
+                    _sourceSubscription = new SingleAssignmentDisposable();
+                    _sourceSubscription.Disposable = parent._sources.SubscribeSafe(this);
+                    _group.Add(_sourceSubscription);
 
-            public void OnNext(IObservable<TSource> value)
-            {
-                var innerSubscription = new SingleAssignmentDisposable();
-                _group.Add(innerSubscription);
-                innerSubscription.Disposable = value.SubscribeSafe(new Iter(this, innerSubscription));
-            }
+                    return _group;
+                }
 
-            public void OnError(Exception error)
-            {
-                lock (_gate)
+                public void OnNext(IObservable<TSource> value)
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        if (_activeCount < _maxConcurrent)
+                        {
+                            _activeCount++;
+                            Subscribe(value);
+                        }
+                        else
+                            _q.Enqueue(value);
+                    }
                 }
-            }
 
-            public void OnCompleted()
-            {
-                _isStopped = true;
-                if (_group.Count == 1)
+                public void OnError(Exception error)
                 {
-                    //
-                    // Notice there can be a race between OnCompleted of the source and any
-                    // of the inner sequences, where both see _group.Count == 1, and one is
-                    // waiting for the lock. There won't be a double OnCompleted observation
-                    // though, because the call to Dispose silences the observer by swapping
-                    // in a NopObserver<T>.
-                    //
                     lock (_gate)
                     {
-                        base._observer.OnCompleted();
+                        base._observer.OnError(error);
                         base.Dispose();
                     }
                 }
-                else
-                {
-                    _sourceSubscription.Dispose();
-                }
-            }
 
-            class Iter : IObserver<TSource>
-            {
-                private readonly _ _parent;
-                private readonly IDisposable _self;
-
-                public Iter(_ parent, IDisposable self)
+                public void OnCompleted()
                 {
-                    _parent = parent;
-                    _self = self;
+                    lock (_gate)
+                    {
+                        _isStopped = true;
+                        if (_activeCount == 0)
+                        {
+                            base._observer.OnCompleted();
+                            base.Dispose();
+                        }
+                        else
+                        {
+                            _sourceSubscription.Dispose();
+                        }
+                    }
                 }
 
-                public void OnNext(TSource value)
+                private void Subscribe(IObservable<TSource> innerSource)
                 {
-                    lock (_parent._gate)
-                        _parent._observer.OnNext(value);
+                    var subscription = new SingleAssignmentDisposable();
+                    _group.Add(subscription);
+                    subscription.Disposable = innerSource.SubscribeSafe(new InnerObserver(this, subscription));
                 }
 
-                public void OnError(Exception error)
+                private sealed class InnerObserver : IObserver<TSource>
                 {
-                    lock (_parent._gate)
+                    private readonly _ _parent;
+                    private readonly IDisposable _self;
+
+                    public InnerObserver(_ parent, IDisposable self)
                     {
-                        _parent._observer.OnError(error);
-                        _parent.Dispose();
+                        _parent = parent;
+                        _self = self;
                     }
-                }
 
-                public void OnCompleted()
-                {
-                    _parent._group.Remove(_self);
-                    if (_parent._isStopped && _parent._group.Count == 1)
+                    public void OnNext(TSource value)
+                    {
+                        lock (_parent._gate)
+                            _parent._observer.OnNext(value);
+                    }
+
+                    public void OnError(Exception error)
                     {
-                        //
-                        // Notice there can be a race between OnCompleted of the source and any
-                        // of the inner sequences, where both see _group.Count == 1, and one is
-                        // waiting for the lock. There won't be a double OnCompleted observation
-                        // though, because the call to Dispose silences the observer by swapping
-                        // in a NopObserver<T>.
-                        //
                         lock (_parent._gate)
                         {
-                            _parent._observer.OnCompleted();
+                            _parent._observer.OnError(error);
                             _parent.Dispose();
                         }
                     }
+
+                    public void OnCompleted()
+                    {
+                        _parent._group.Remove(_self);
+                        lock (_parent._gate)
+                        {
+                            if (_parent._q.Count > 0)
+                            {
+                                var s = _parent._q.Dequeue();
+                                _parent.Subscribe(s);
+                            }
+                            else
+                            {
+                                _parent._activeCount--;
+                                if (_parent._isStopped && _parent._activeCount == 0)
+                                {
+                                    _parent._observer.OnCompleted();
+                                    _parent.Dispose();
+                                }
+                            }
+                        }
+                    }
                 }
             }
         }
 
-        class MergeConcurrent : Sink<TSource>, IObserver<IObservable<TSource>>
+        internal sealed class Observables : Producer<TSource>
         {
-            private readonly Merge<TSource> _parent;
+            private readonly IObservable<IObservable<TSource>> _sources;
 
-            public MergeConcurrent(Merge<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Observables(IObservable<IObservable<TSource>> sources)
             {
-                _parent = parent;
+                _sources = sources;
             }
 
-            private object _gate;
-            private Queue<IObservable<TSource>> _q;
-            private bool _isStopped;
-            private SingleAssignmentDisposable _sourceSubscription;
-            private CompositeDisposable _group;
-            private int _activeCount = 0;
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
+            }
 
-            public IDisposable Run()
+            private sealed class _ : Sink<TSource>, IObserver<IObservable<TSource>>
             {
-                _gate = new object();
-                _q = new Queue<IObservable<TSource>>();
-                _isStopped = false;
-                _activeCount = 0;
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                }
 
-                _group = new CompositeDisposable();
-                _sourceSubscription = new SingleAssignmentDisposable();
-                _sourceSubscription.Disposable = _parent._sources.SubscribeSafe(this);
-                _group.Add(_sourceSubscription);
+                private object _gate;
+                private bool _isStopped;
+                private CompositeDisposable _group;
+                private SingleAssignmentDisposable _sourceSubscription;
 
-                return _group;
-            }
+                public IDisposable Run(Observables parent)
+                {
+                    _gate = new object();
+                    _isStopped = false;
+                    _group = new CompositeDisposable();
 
-            public void OnNext(IObservable<TSource> value)
-            {
-                lock (_gate)
+                    _sourceSubscription = new SingleAssignmentDisposable();
+                    _group.Add(_sourceSubscription);
+                    _sourceSubscription.Disposable = parent._sources.SubscribeSafe(this);
+
+                    return _group;
+                }
+
+                public void OnNext(IObservable<TSource> value)
                 {
-                    if (_activeCount < _parent._maxConcurrent)
-                    {
-                        _activeCount++;
-                        Subscribe(value);
-                    }
-                    else
-                        _q.Enqueue(value);
+                    var innerSubscription = new SingleAssignmentDisposable();
+                    _group.Add(innerSubscription);
+                    innerSubscription.Disposable = value.SubscribeSafe(new InnerObserver(this, innerSubscription));
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                lock (_gate)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
-            }
 
-            public void OnCompleted()
-            {
-                lock (_gate)
+                public void OnCompleted()
                 {
                     _isStopped = true;
-                    if (_activeCount == 0)
+                    if (_group.Count == 1)
                     {
-                        base._observer.OnCompleted();
-                        base.Dispose();
+                        //
+                        // Notice there can be a race between OnCompleted of the source and any
+                        // of the inner sequences, where both see _group.Count == 1, and one is
+                        // waiting for the lock. There won't be a double OnCompleted observation
+                        // though, because the call to Dispose silences the observer by swapping
+                        // in a NopObserver<T>.
+                        //
+                        lock (_gate)
+                        {
+                            base._observer.OnCompleted();
+                            base.Dispose();
+                        }
                     }
                     else
                     {
                         _sourceSubscription.Dispose();
                     }
                 }
-            }
-
-            private void Subscribe(IObservable<TSource> innerSource)
-            {
-                var subscription = new SingleAssignmentDisposable();
-                _group.Add(subscription);
-                subscription.Disposable = innerSource.SubscribeSafe(new Iter(this, subscription));
-            }
 
-            class Iter : IObserver<TSource>
-            {
-                private readonly MergeConcurrent _parent;
-                private readonly IDisposable _self;
-
-                public Iter(MergeConcurrent parent, IDisposable self)
+                private sealed class InnerObserver : IObserver<TSource>
                 {
-                    _parent = parent;
-                    _self = self;
-                }
+                    private readonly _ _parent;
+                    private readonly IDisposable _self;
 
-                public void OnNext(TSource value)
-                {
-                    lock (_parent._gate)
-                        _parent._observer.OnNext(value);
-                }
+                    public InnerObserver(_ parent, IDisposable self)
+                    {
+                        _parent = parent;
+                        _self = self;
+                    }
 
-                public void OnError(Exception error)
-                {
-                    lock (_parent._gate)
+                    public void OnNext(TSource value)
                     {
-                        _parent._observer.OnError(error);
-                        _parent.Dispose();
+                        lock (_parent._gate)
+                            _parent._observer.OnNext(value);
                     }
-                }
 
-                public void OnCompleted()
-                {
-                    _parent._group.Remove(_self);
-                    lock (_parent._gate)
+                    public void OnError(Exception error)
                     {
-                        if (_parent._q.Count > 0)
+                        lock (_parent._gate)
                         {
-                            var s = _parent._q.Dequeue();
-                            _parent.Subscribe(s);
+                            _parent._observer.OnError(error);
+                            _parent.Dispose();
                         }
-                        else
+                    }
+
+                    public void OnCompleted()
+                    {
+                        _parent._group.Remove(_self);
+                        if (_parent._isStopped && _parent._group.Count == 1)
                         {
-                            _parent._activeCount--;
-                            if (_parent._isStopped && _parent._activeCount == 0)
+                            //
+                            // Notice there can be a race between OnCompleted of the source and any
+                            // of the inner sequences, where both see _group.Count == 1, and one is
+                            // waiting for the lock. There won't be a double OnCompleted observation
+                            // though, because the call to Dispose silences the observer by swapping
+                            // in a NopObserver<T>.
+                            //
+                            lock (_parent._gate)
                             {
                                 _parent._observer.OnCompleted();
                                 _parent.Dispose();
@@ -298,90 +289,104 @@ namespace System.Reactive.Linq.ObservableImpl
             }
         }
 
-        class MergeImpl : Sink<TSource>, IObserver<Task<TSource>>
+        internal sealed class Tasks : Producer<TSource>
         {
-            private readonly Merge<TSource> _parent;
+            private readonly IObservable<Task<TSource>> _sources;
 
-            public MergeImpl(Merge<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Tasks(IObservable<Task<TSource>> sources)
             {
-                _parent = parent;
+                _sources = sources;
             }
 
-            private object _gate;
-            private volatile int _count;
-
-            public IDisposable Run()
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _gate = new object();
-                _count = 1;
-
-                return _parent._sourcesT.SubscribeSafe(this);
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            public void OnNext(Task<TSource> value)
+            private sealed class _ : Sink<TSource>, IObserver<Task<TSource>>
             {
-                Interlocked.Increment(ref _count);
-                if (value.IsCompleted)
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    OnCompletedTask(value);
                 }
-                else
+
+                private object _gate;
+                private volatile int _count;
+
+                public IDisposable Run(Tasks parent)
                 {
-                    value.ContinueWith(OnCompletedTask);
+                    _gate = new object();
+                    _count = 1;
+
+                    return parent._sources.SubscribeSafe(this);
                 }
-            }
 
-            private void OnCompletedTask(Task<TSource> task)
-            {
-                switch (task.Status)
+                public void OnNext(Task<TSource> value)
                 {
-                    case TaskStatus.RanToCompletion:
-                        {
-                            lock (_gate)
-                                base._observer.OnNext(task.Result);
+                    Interlocked.Increment(ref _count);
+                    if (value.IsCompleted)
+                    {
+                        OnCompletedTask(value);
+                    }
+                    else
+                    {
+                        value.ContinueWith(OnCompletedTask);
+                    }
+                }
 
-                            OnCompleted();
-                        }
-                        break;
-                    case TaskStatus.Faulted:
-                        {
-                            lock (_gate)
+                private void OnCompletedTask(Task<TSource> task)
+                {
+                    switch (task.Status)
+                    {
+                        case TaskStatus.RanToCompletion:
                             {
-                                base._observer.OnError(task.Exception.InnerException);
-                                base.Dispose();
+                                lock (_gate)
+                                    base._observer.OnNext(task.Result);
+
+                                OnCompleted();
                             }
-                        }
-                        break;
-                    case TaskStatus.Canceled:
-                        {
-                            lock (_gate)
+                            break;
+                        case TaskStatus.Faulted:
                             {
-                                base._observer.OnError(new TaskCanceledException(task));
-                                base.Dispose();
+                                lock (_gate)
+                                {
+                                    base._observer.OnError(task.Exception.InnerException);
+                                    base.Dispose();
+                                }
                             }
-                        }
-                        break;
+                            break;
+                        case TaskStatus.Canceled:
+                            {
+                                lock (_gate)
+                                {
+                                    base._observer.OnError(new TaskCanceledException(task));
+                                    base.Dispose();
+                                }
+                            }
+                            break;
+                    }
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                lock (_gate)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
-            }
 
-            public void OnCompleted()
-            {
-                if (Interlocked.Decrement(ref _count) == 0)
+                public void OnCompleted()
                 {
-                    lock (_gate)
+                    if (Interlocked.Decrement(ref _count) == 0)
                     {
-                        base._observer.OnCompleted();
-                        base.Dispose();
+                        lock (_gate)
+                        {
+                            base._observer.OnCompleted();
+                            base.Dispose();
+                        }
                     }
                 }
             }

+ 22 - 22
Rx.NET/Source/src/System.Reactive/Linq/Observable/Min.cs

@@ -22,28 +22,28 @@ namespace System.Reactive.Linq.ObservableImpl
             // LINQ to Objects makes this distinction in order to make [Min|Max] of an empty collection of reference type objects equal to null.
             if (default(TSource) == null)
             {
-                var sink = new _(this, observer, cancel);
+                var sink = new Null(_comparer, observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
             else
             {
-                var sink = new Delta(this, observer, cancel);
+                var sink = new NonNull(_comparer, observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
         }
 
-        class Delta : Sink<TSource>, IObserver<TSource>
+        private sealed class NonNull : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Min<TSource> _parent;
+            private readonly IComparer<TSource> _comparer;
             private bool _hasValue;
             private TSource _lastValue;
 
-            public Delta(Min<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public NonNull(IComparer<TSource> comparer, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _comparer = comparer;
 
                 _hasValue = false;
                 _lastValue = default(TSource);
@@ -57,7 +57,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                     try
                     {
-                        comparison = _parent._comparer.Compare(value, _lastValue);
+                        comparison = _comparer.Compare(value, _lastValue);
                     }
                     catch (Exception ex)
                     {
@@ -100,15 +100,15 @@ namespace System.Reactive.Linq.ObservableImpl
             }
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class Null : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Min<TSource> _parent;
+            private readonly IComparer<TSource> _comparer;
             private TSource _lastValue;
 
-            public _(Min<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public Null(IComparer<TSource> comparer, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _comparer = comparer;
 
                 _lastValue = default(TSource);
             }
@@ -127,7 +127,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                         try
                         {
-                            comparison = _parent._comparer.Compare(value, _lastValue);
+                            comparison = _comparer.Compare(value, _lastValue);
                         }
                         catch (Exception ex)
                         {
@@ -175,7 +175,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double>, IObserver<double>
+        private sealed class _ : Sink<double>, IObserver<double>
         {
             private bool _hasValue;
             private double _lastValue;
@@ -242,7 +242,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float>, IObserver<float>
+        private sealed class _ : Sink<float>, IObserver<float>
         {
             private bool _hasValue;
             private float _lastValue;
@@ -309,7 +309,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal>, IObserver<decimal>
+        private sealed class _ : Sink<decimal>, IObserver<decimal>
         {
             private bool _hasValue;
             private decimal _lastValue;
@@ -376,7 +376,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<int>, IObserver<int>
+        private sealed class _ : Sink<int>, IObserver<int>
         {
             private bool _hasValue;
             private int _lastValue;
@@ -443,7 +443,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<long>, IObserver<long>
+        private sealed class _ : Sink<long>, IObserver<long>
         {
             private bool _hasValue;
             private long _lastValue;
@@ -510,7 +510,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double?>, IObserver<double?>
+        private sealed class _ : Sink<double?>, IObserver<double?>
         {
             private double? _lastValue;
 
@@ -569,7 +569,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float?>, IObserver<float?>
+        private sealed class _ : Sink<float?>, IObserver<float?>
         {
             private float? _lastValue;
 
@@ -628,7 +628,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal?>, IObserver<decimal?>
+        private sealed class _ : Sink<decimal?>, IObserver<decimal?>
         {
             private decimal? _lastValue;
 
@@ -687,7 +687,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<int?>, IObserver<int?>
+        private sealed class _ : Sink<int?>, IObserver<int?>
         {
             private int? _lastValue;
 
@@ -746,7 +746,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<long?>, IObserver<long?>
+        private sealed class _ : Sink<long?>, IObserver<long?>
         {
             private long? _lastValue;
 

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/MinBy.cs

@@ -26,7 +26,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<IList<TSource>>, IObserver<TSource>
+        private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
         {
             private readonly MinBy<TSource, TKey> _parent;
             private bool _hasValue;

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/MostRecent.cs

@@ -19,7 +19,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return new _(_initialValue, subscription);
         }
 
-        class _ : PushToPullSink<TSource, TSource>
+        private sealed class _ : PushToPullSink<TSource, TSource>
         {
             public _(TSource initialValue, IDisposable subscription)
                 : base(subscription)

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

@@ -22,30 +22,27 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TResult>, IObserver<TResult>
+        private sealed class _ : Sink<TResult>, IObserver<TResult>
         {
-            private readonly Multicast<TSource, TIntermediate, TResult> _parent;
-
-            public _(Multicast<TSource, TIntermediate, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(Multicast<TSource, TIntermediate, TResult> parent)
             {
                 var observable = default(IObservable<TResult>);
                 var connectable = default(IConnectableObservable<TIntermediate>);
                 try
                 {
-                    var subject = _parent._subjectSelector();
-                    connectable = new ConnectableObservable<TSource, TIntermediate>(_parent._source, subject);
-                    observable = _parent._selector(connectable);
+                    var subject =parent._subjectSelector();
+                    connectable = new ConnectableObservable<TSource, TIntermediate>(parent._source, subject);
+                    observable = parent._selector(connectable);
                 }
                 catch (Exception exception)
                 {

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/Next.cs

@@ -18,7 +18,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return new _(subscription);
         }
 
-        class _ : PushToPullSink<TSource, TSource>
+        private sealed class _ : PushToPullSink<TSource, TSource>
         {
             private readonly object _gate;
             private readonly SemaphoreSlim _semaphore;

+ 0 - 81
Rx.NET/Source/src/System.Reactive/Linq/Observable/ObserveOn.cs

@@ -1,81 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-
-using System.Reactive.Concurrency;
-using System.Threading;
-
-namespace System.Reactive.Linq.ObservableImpl
-{
-    internal sealed class ObserveOn<TSource> : Producer<TSource>
-    {
-        private readonly IObservable<TSource> _source;
-        private readonly IScheduler _scheduler;
-        private readonly SynchronizationContext _context;
-
-        public ObserveOn(IObservable<TSource> source, IScheduler scheduler)
-        {
-            _source = source;
-            _scheduler = scheduler;
-        }
-
-        public ObserveOn(IObservable<TSource> source, SynchronizationContext context)
-        {
-            _source = source;
-            _context = context;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_context != null)
-            {
-                var sink = new ObserveOnImpl(this, observer, cancel);
-                setSink(sink);
-                return _source.Subscribe(sink);
-            }
-            else
-            {
-                var sink = new ObserveOnObserver<TSource>(_scheduler, observer, cancel);
-                setSink(sink);
-                return _source.Subscribe(sink);
-            }
-        }
-
-        class ObserveOnImpl : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly ObserveOn<TSource> _parent;
-
-            public ObserveOnImpl(ObserveOn<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
-            }
-
-            public void OnNext(TSource value)
-            {
-                _parent._context.PostWithStartComplete(() =>
-                {
-                    base._observer.OnNext(value);
-                });
-            }
-
-            public void OnError(Exception error)
-            {
-                _parent._context.PostWithStartComplete(() =>
-                {
-                    base._observer.OnError(error);
-                    base.Dispose();
-                });
-            }
-
-            public void OnCompleted()
-            {
-                _parent._context.PostWithStartComplete(() =>
-                {
-                    base._observer.OnCompleted();
-                    base.Dispose();
-                });
-            }
-        }
-    }
-}

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/OfType.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TResult>, IObserver<TSource>
+        private sealed class _ : Sink<TResult>, IObserver<TSource>
         {
             public _(IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)

+ 1 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/OnErrorResumeNext.cs

@@ -22,7 +22,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return sink.Run(_sources);
         }
 
-        class _ : TailRecursiveSink<TSource>
+        private sealed class _ : TailRecursiveSink<TSource>
         {
             public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)

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

@@ -8,7 +8,7 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    abstract class PushToPullAdapter<TSource, TResult> : IEnumerable<TResult>
+    internal abstract class PushToPullAdapter<TSource, TResult> : IEnumerable<TResult>
     {
         private readonly IObservable<TSource> _source;
 
@@ -17,10 +17,7 @@ namespace System.Reactive.Linq.ObservableImpl
             _source = source;
         }
 
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
+        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 
         public IEnumerator<TResult> GetEnumerator()
         {
@@ -33,7 +30,7 @@ namespace System.Reactive.Linq.ObservableImpl
         protected abstract PushToPullSink<TSource, TResult> Run(IDisposable subscription);
     }
 
-    abstract class PushToPullSink<TSource, TResult> : IObserver<TSource>, IEnumerator<TResult>, IDisposable
+    internal abstract class PushToPullSink<TSource, TResult> : IObserver<TSource>, IEnumerator<TResult>, IDisposable
     {
         private readonly IDisposable _subscription;
 
@@ -76,10 +73,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private set;
         }
 
-        object IEnumerator.Current
-        {
-            get { return Current; }
-        }
+        object IEnumerator.Current => Current;
 
         public void Reset()
         {

+ 13 - 11
Rx.NET/Source/src/System.Reactive/Linq/Observable/Range.cs

@@ -24,37 +24,39 @@ namespace System.Reactive.Linq.ObservableImpl
         {
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_scheduler);
         }
 
-        class _ : Sink<int>
+        private sealed class _ : Sink<int>
         {
-            private readonly Range _parent;
+            private readonly int _start;
+            private readonly int _count;
 
             public _(Range parent, IObserver<int> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _start = parent._start;
+                _count = parent._count;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(IScheduler scheduler)
             {
-                var longRunning = _parent._scheduler.AsLongRunning();
+                var longRunning = scheduler.AsLongRunning();
                 if (longRunning != null)
                 {
                     return longRunning.ScheduleLongRunning(0, Loop);
                 }
                 else
                 {
-                    return _parent._scheduler.Schedule(0, LoopRec);
+                    return scheduler.Schedule(0, LoopRec);
                 }
             }
 
             private void Loop(int i, ICancelable cancel)
             {
-                while (!cancel.IsDisposed && i < _parent._count)
+                while (!cancel.IsDisposed && i < _count)
                 {
-                    base._observer.OnNext(_parent._start + i);
+                    base._observer.OnNext(_start + i);
                     i++;
                 }
 
@@ -66,9 +68,9 @@ namespace System.Reactive.Linq.ObservableImpl
 
             private void LoopRec(int i, Action<int> recurse)
             {
-                if (i < _parent._count)
+                if (i < _count)
                 {
-                    base._observer.OnNext(_parent._start + i);
+                    base._observer.OnNext(_start + i);
                     recurse(i + 1);
                 }
                 else

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

@@ -25,30 +25,27 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly RefCount<TSource> _parent;
-
-            public _(RefCount<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(RefCount<TSource> parent)
             {
-                var subscription = _parent._source.SubscribeSafe(this);
+                var subscription = parent._source.SubscribeSafe(this);
 
-                lock (_parent._gate)
+                lock (parent._gate)
                 {
-                    if (++_parent._count == 1)
+                    if (++parent._count == 1)
                     {
-                        _parent._connectableSubscription = _parent._source.Connect();
+                        parent._connectableSubscription = parent._source.Connect();
                     }
                 }
 
@@ -56,11 +53,11 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     subscription.Dispose();
 
-                    lock (_parent._gate)
+                    lock (parent._gate)
                     {
-                        if (--_parent._count == 0)
+                        if (--parent._count == 0)
                         {
-                            _parent._connectableSubscription.Dispose();
+                            parent._connectableSubscription.Dispose();
                         }
                     }
                 });

+ 100 - 78
Rx.NET/Source/src/System.Reactive/Linq/Observable/Repeat.cs

@@ -7,119 +7,141 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Repeat<TResult> : Producer<TResult>
+    internal static class Repeat<TResult>
     {
-        private readonly TResult _value;
-        private readonly int? _repeatCount;
-        private readonly IScheduler _scheduler;
-
-        public Repeat(TResult value, int? repeatCount, IScheduler scheduler)
+        internal sealed class Forever : Producer<TResult>
         {
-            _value = value;
-            _repeatCount = repeatCount;
-            _scheduler = scheduler;
-        }
-
-        protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            var sink = new _(this, observer, cancel);
-            setSink(sink);
-            return sink.Run();
-        }
+            private readonly TResult _value;
+            private readonly IScheduler _scheduler;
 
-        class _ : Sink<TResult>
-        {
-            private readonly Repeat<TResult> _parent;
+            public Forever(TResult value, IScheduler scheduler)
+            {
+                _value = value;
+                _scheduler = scheduler;
+            }
 
-            public _(Repeat<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _parent = parent;
+                var sink = new _(_value, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            public IDisposable Run()
+            private sealed class _ : Sink<TResult>
             {
-                var longRunning = _parent._scheduler.AsLongRunning();
-                if (longRunning != null)
+                private readonly TResult _value;
+
+                public _(TResult value, IObserver<TResult> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    return Run(longRunning);
+                    _value = value;
                 }
-                else
+
+                public IDisposable Run(Forever parent)
                 {
-                    return Run(_parent._scheduler);
+                    var longRunning = parent._scheduler.AsLongRunning();
+                    if (longRunning != null)
+                    {
+                        return longRunning.ScheduleLongRunning(LoopInf);
+                    }
+                    else
+                    {
+                        return parent._scheduler.Schedule(LoopRecInf);
+                    }
                 }
-            }
 
-            private IDisposable Run(IScheduler scheduler)
-            {
-                if (_parent._repeatCount == null)
+                private void LoopRecInf(Action recurse)
                 {
-                    return scheduler.Schedule(LoopRecInf);
+                    base._observer.OnNext(_value);
+                    recurse();
                 }
-                else
+
+                private void LoopInf(ICancelable cancel)
                 {
-                    return scheduler.Schedule(_parent._repeatCount.Value, LoopRec);
+                    var value = _value;
+                    while (!cancel.IsDisposed)
+                        base._observer.OnNext(value);
+
+                    base.Dispose();
                 }
             }
+        }
+
+        internal sealed class Count : Producer<TResult>
+        {
+            private readonly TResult _value;
+            private readonly IScheduler _scheduler;
+            private readonly int _repeatCount;
 
-            private void LoopRecInf(Action recurse)
+            public Count(TResult value, int repeatCount, IScheduler scheduler)
             {
-                base._observer.OnNext(_parent._value);
-                recurse();
+                _value = value;
+                _scheduler = scheduler;
+                _repeatCount = repeatCount;
             }
 
-            private void LoopRec(int n, Action<int> recurse)
+            protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                if (n > 0)
-                {
-                    base._observer.OnNext(_parent._value);
-                    n--;
-                }
-
-                if (n == 0)
-                {
-                    base._observer.OnCompleted();
-                    base.Dispose();
-                    return;
-                }
-
-                recurse(n);
+                var sink = new _(_value, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            private IDisposable Run(ISchedulerLongRunning scheduler)
+            private sealed class _ : Sink<TResult>
             {
-                if (_parent._repeatCount == null)
+                private readonly TResult _value;
+
+                public _(TResult value, IObserver<TResult> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    return scheduler.ScheduleLongRunning(LoopInf);
+                    _value = value;
                 }
-                else
+
+                public IDisposable Run(Count parent)
                 {
-                    return scheduler.ScheduleLongRunning(_parent._repeatCount.Value, Loop);
+                    var longRunning = parent._scheduler.AsLongRunning();
+                    if (longRunning != null)
+                    {
+                        return longRunning.ScheduleLongRunning(parent._repeatCount, Loop);
+                    }
+                    else
+                    {
+                        return parent._scheduler.Schedule(parent._repeatCount, LoopRec);
+                    }
                 }
-            }
 
-            private void LoopInf(ICancelable cancel)
-            {
-                var value = _parent._value;
-                while (!cancel.IsDisposed)
-                    base._observer.OnNext(value);
-
-                base.Dispose();
-            }
-
-            private void Loop(int n, ICancelable cancel)
-            {
-                var value = _parent._value;
-                while (n > 0 && !cancel.IsDisposed)
+                private void LoopRec(int n, Action<int> recurse)
                 {
-                    base._observer.OnNext(value);
-                    n--;
+                    if (n > 0)
+                    {
+                        base._observer.OnNext(_value);
+                        n--;
+                    }
+
+                    if (n == 0)
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                        return;
+                    }
+
+                    recurse(n);
                 }
 
-                if (!cancel.IsDisposed)
-                    base._observer.OnCompleted();
+                private void Loop(int n, ICancelable cancel)
+                {
+                    var value = _value;
+                    while (n > 0 && !cancel.IsDisposed)
+                    {
+                        base._observer.OnNext(value);
+                        n--;
+                    }
+
+                    if (!cancel.IsDisposed)
+                        base._observer.OnCompleted();
 
-                base.Dispose();
+                    base.Dispose();
+                }
             }
         }
     }

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

@@ -19,29 +19,29 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_value, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_scheduler);
         }
 
-        class _ : Sink<TResult>
+        private sealed class _ : Sink<TResult>
         {
-            private readonly Return<TResult> _parent;
+            private readonly TResult _value;
 
-            public _(Return<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(TResult value, IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _value = value;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(IScheduler scheduler)
             {
-                return _parent._scheduler.Schedule(Invoke);
+                return scheduler.Schedule(Invoke);
             }
 
             private void Invoke()
             {
-                base._observer.OnNext(_parent._value);
+                base._observer.OnNext(_value);
                 base._observer.OnCompleted();
                 base.Dispose();
             }

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

@@ -20,38 +20,33 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Sample<TSource, TSample> _parent;
+            private readonly object _gate = new object();
 
-            public _(Sample<TSource, TSample> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            private object _gate;
-
             private IDisposable _sourceSubscription;
 
             private bool _hasValue;
             private TSource _value;
             private bool _atEnd;
 
-            public IDisposable Run()
+            public IDisposable Run(Sample<TSource, TSample> parent)
             {
-                _gate = new object();
-
                 var sourceSubscription = new SingleAssignmentDisposable();
                 _sourceSubscription = sourceSubscription;
-                sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+                sourceSubscription.Disposable = parent._source.SubscribeSafe(this);
 
-                var samplerSubscription = _parent._sampler.SubscribeSafe(new SampleImpl(this));
+                var samplerSubscription = parent._sampler.SubscribeSafe(new SampleObserver(this));
 
                 return StableCompositeDisposable.Create(_sourceSubscription, samplerSubscription);
             }
@@ -83,11 +78,11 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class SampleImpl : IObserver<TSample>
+            private sealed class SampleObserver : IObserver<TSample>
             {
                 private readonly _ _parent;
 
-                public SampleImpl(_ parent)
+                public SampleObserver(_ parent)
                 {
                     _parent = parent;
                 }
@@ -156,40 +151,35 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Sample<TSource> _parent;
+            private object _gate = new object();
 
-            public _(Sample<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            private object _gate;
-
             private IDisposable _sourceSubscription;
 
             private bool _hasValue;
             private TSource _value;
             private bool _atEnd;
 
-            public IDisposable Run()
+            public IDisposable Run(Sample<TSource> parent)
             {
-                _gate = new object();
-
                 var sourceSubscription = new SingleAssignmentDisposable();
                 _sourceSubscription = sourceSubscription;
-                sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+                sourceSubscription.Disposable = parent._source.SubscribeSafe(this);
 
                 return StableCompositeDisposable.Create(
                     sourceSubscription,
-                    _parent._scheduler.SchedulePeriodic(_parent._interval, Tick)
+                    parent._scheduler.SchedulePeriodic(parent._interval, Tick)
                 );
             }
 

+ 13 - 19
Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs

@@ -24,31 +24,23 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TAccumulate>, IObserver<TSource>
+        private sealed class _ : Sink<TAccumulate>, IObserver<TSource>
         {
-            private readonly Scan<TSource, TAccumulate> _parent;
+            private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
             private TAccumulate _accumulation;
-            private bool _hasAccumulation;
 
             public _(Scan<TSource, TAccumulate> parent, IObserver<TAccumulate> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _accumulation = default(TAccumulate);
-                _hasAccumulation = false;
+                _accumulator = parent._accumulator;
+                _accumulation = parent._seed;
             }
 
             public void OnNext(TSource value)
             {
                 try
                 {
-                    if (_hasAccumulation)
-                        _accumulation = _parent._accumulator(_accumulation, value);
-                    else
-                    {
-                        _accumulation = _parent._accumulator(_parent._seed, value);
-                        _hasAccumulation = true;
-                    }
+                    _accumulation = _accumulator(_accumulation, value);
                 }
                 catch (Exception exception)
                 {
@@ -87,21 +79,21 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_accumulator, observer, cancel);
             setSink(sink);
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Scan<TSource> _parent;
+            private readonly Func<TSource, TSource, TSource> _accumulator;
             private TSource _accumulation;
             private bool _hasAccumulation;
 
-            public _(Scan<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(Func<TSource, TSource, TSource> accumulator, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _accumulator = accumulator;
                 _accumulation = default(TSource);
                 _hasAccumulation = false;
             }
@@ -111,7 +103,9 @@ namespace System.Reactive.Linq.ObservableImpl
                 try
                 {
                     if (_hasAccumulation)
-                        _accumulation = _parent._accumulator(_accumulation, value);
+                    {
+                        _accumulation = _accumulator(_accumulation, value);
+                    }
                     else
                     {
                         _accumulation = value;

+ 85 - 79
Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs

@@ -4,119 +4,125 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Select<TSource, TResult> : Producer<TResult>
+    internal static class Select<TSource, TResult>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, TResult> _selector;
-        private readonly Func<TSource, int, TResult> _selectorI;
-
-        public Select(IObservable<TSource> source, Func<TSource, TResult> selector)
-        {
-            _source = source;
-            _selector = selector;
-        }
-
-        public Select(IObservable<TSource> source, Func<TSource, int, TResult> selector)
+        internal sealed class Selector : Producer<TResult>
         {
-            _source = source;
-            _selectorI = selector;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, TResult> _selector;
 
-        protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_selector != null)
+            public Selector(IObservable<TSource> source, Func<TSource, TResult> selector)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
+                _selector = selector;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new SelectImpl(this, observer, cancel);
+                var sink = new _(_selector, observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
-
-        class _ : Sink<TResult>, IObserver<TSource>
-        {
-            private readonly Select<TSource, TResult> _parent;
 
-            public _(Select<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TResult>, IObserver<TSource>
             {
-                _parent = parent;
-            }
+                private readonly Func<TSource, TResult> _selector;
 
-            public void OnNext(TSource value)
-            {
-                var result = default(TResult);
-                try
+                public _(Func<TSource, TResult> selector, IObserver<TResult> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    result = _parent._selector(value);
+                    _selector = selector;
                 }
-                catch (Exception exception)
+
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnError(exception);
+                    var result = default(TResult);
+                    try
+                    {
+                        result = _selector(value);
+                    }
+                    catch (Exception exception)
+                    {
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnNext(result);
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
                     base.Dispose();
-                    return;
                 }
 
-                base._observer.OnNext(result);
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
+        }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+        internal sealed class SelectorIndexed : Producer<TResult>
+        {
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, int, TResult> _selector;
 
-            public void OnCompleted()
+            public SelectorIndexed(IObservable<TSource> source, Func<TSource, int, TResult> selector)
             {
-                base._observer.OnCompleted();
-                base.Dispose();
+                _source = source;
+                _selector = selector;
             }
-        }
-
-        class SelectImpl : Sink<TResult>, IObserver<TSource>
-        {
-            private readonly Select<TSource, TResult> _parent;
-            private int _index;
 
-            public SelectImpl(Select<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _parent = parent;
-                _index = 0;
+                var sink = new _(_selector, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TResult>, IObserver<TSource>
             {
-                var result = default(TResult);
-                try
+                private readonly Func<TSource, int, TResult> _selector;
+                private int _index;
+
+                public _(Func<TSource, int, TResult> selector, IObserver<TResult> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    result = _parent._selectorI(value, checked(_index++));
+                    _selector = selector;
+                    _index = 0;
                 }
-                catch (Exception exception)
+
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnError(exception);
-                    base.Dispose();
-                    return;
+                    var result = default(TResult);
+                    try
+                    {
+                        result = _selector(value, checked(_index++));
+                    }
+                    catch (Exception exception)
+                    {
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                        return;
+                    }
+
+                    base._observer.OnNext(result);
                 }
 
-                base._observer.OnNext(result);
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
 
-            public void OnCompleted()
-            {
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 668 - 735
Rx.NET/Source/src/System.Reactive/Linq/Observable/SelectMany.cs


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

@@ -7,224 +7,210 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class SequenceEqual<TSource> : Producer<bool>
+    internal static class SequenceEqual<TSource>
     {
-        private readonly IObservable<TSource> _first;
-        private readonly IObservable<TSource> _second;
-        private readonly IEnumerable<TSource> _secondE;
-        private readonly IEqualityComparer<TSource> _comparer;
-
-        public SequenceEqual(IObservable<TSource> first, IObservable<TSource> second, IEqualityComparer<TSource> comparer)
-        {
-            _first = first;
-            _second = second;
-            _comparer = comparer;
-        }
-
-        public SequenceEqual(IObservable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+        internal sealed class Observable : Producer<bool>
         {
-            _first = first;
-            _secondE = second;
-            _comparer = comparer;
-        }
+            private readonly IObservable<TSource> _first;
+            private readonly IObservable<TSource> _second;
+            private readonly IEqualityComparer<TSource> _comparer;
 
-        protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_second != null)
+            public Observable(IObservable<TSource> first, IObservable<TSource> second, IEqualityComparer<TSource> comparer)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _first = first;
+                _second = second;
+                _comparer = comparer;
             }
-            else
+
+            protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new SequenceEqualImpl(this, observer, cancel);
+                var sink = new _(_comparer, observer, cancel);
                 setSink(sink);
-                return sink.Run();
+                return sink.Run(this);
             }
-        }
-
-        class _ : Sink<bool>
-        {
-            private readonly SequenceEqual<TSource> _parent;
 
-            public _(SequenceEqual<TSource> parent, IObserver<bool> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<bool>
             {
-                _parent = parent;
-            }
+                private readonly IEqualityComparer<TSource> _comparer;
 
-            private object _gate;
-            private bool _donel;
-            private bool _doner;
-            private Queue<TSource> _ql;
-            private Queue<TSource> _qr;
-
-            public IDisposable Run()
-            {
-                _gate = new object();
-                _donel = false;
-                _doner = false;
-                _ql = new Queue<TSource>();
-                _qr = new Queue<TSource>();
-
-                return StableCompositeDisposable.Create
-                (
-                    _parent._first.SubscribeSafe(new F(this)),
-                    _parent._second.SubscribeSafe(new S(this))
-                );
-            }
+                public _(IEqualityComparer<TSource> comparer, IObserver<bool> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _comparer = comparer;
+                }
 
-            class F : IObserver<TSource>
-            {
-                private readonly _ _parent;
+                private object _gate;
+                private bool _donel;
+                private bool _doner;
+                private Queue<TSource> _ql;
+                private Queue<TSource> _qr;
 
-                public F(_ parent)
+                public IDisposable Run(Observable parent)
                 {
-                    _parent = parent;
+                    _gate = new object();
+                    _donel = false;
+                    _doner = false;
+                    _ql = new Queue<TSource>();
+                    _qr = new Queue<TSource>();
+
+                    return StableCompositeDisposable.Create
+                    (
+                        parent._first.SubscribeSafe(new FirstObserver(this)),
+                        parent._second.SubscribeSafe(new SecondObserver(this))
+                    );
                 }
 
-                public void OnNext(TSource value)
+                private sealed class FirstObserver : IObserver<TSource>
                 {
-                    lock (_parent._gate)
+                    private readonly _ _parent;
+
+                    public FirstObserver(_ parent)
                     {
-                        if (_parent._qr.Count > 0)
+                        _parent = parent;
+                    }
+
+                    public void OnNext(TSource value)
+                    {
+                        lock (_parent._gate)
                         {
-                            var equal = false;
-                            var v = _parent._qr.Dequeue();
-                            try
-                            {
-                                equal = _parent._parent._comparer.Equals(value, v);
-                            }
-                            catch (Exception exception)
+                            if (_parent._qr.Count > 0)
                             {
-                                _parent._observer.OnError(exception);
-                                _parent.Dispose();
-                                return;
+                                var equal = false;
+                                var v = _parent._qr.Dequeue();
+                                try
+                                {
+                                    equal = _parent._comparer.Equals(value, v);
+                                }
+                                catch (Exception exception)
+                                {
+                                    _parent._observer.OnError(exception);
+                                    _parent.Dispose();
+                                    return;
+                                }
+                                if (!equal)
+                                {
+                                    _parent._observer.OnNext(false);
+                                    _parent._observer.OnCompleted();
+                                    _parent.Dispose();
+                                }
                             }
-                            if (!equal)
+                            else if (_parent._doner)
                             {
                                 _parent._observer.OnNext(false);
                                 _parent._observer.OnCompleted();
                                 _parent.Dispose();
                             }
+                            else
+                                _parent._ql.Enqueue(value);
                         }
-                        else if (_parent._doner)
-                        {
-                            _parent._observer.OnNext(false);
-                            _parent._observer.OnCompleted();
-                            _parent.Dispose();
-                        }
-                        else
-                            _parent._ql.Enqueue(value);
                     }
-                }
 
-                public void OnError(Exception error)
-                {
-                    lock (_parent._gate)
+                    public void OnError(Exception error)
                     {
-                        _parent._observer.OnError(error);
-                        _parent.Dispose();
+                        lock (_parent._gate)
+                        {
+                            _parent._observer.OnError(error);
+                            _parent.Dispose();
+                        }
                     }
-                }
 
-                public void OnCompleted()
-                {
-                    lock (_parent._gate)
+                    public void OnCompleted()
                     {
-                        _parent._donel = true;
-                        if (_parent._ql.Count == 0)
+                        lock (_parent._gate)
                         {
-                            if (_parent._qr.Count > 0)
-                            {
-                                _parent._observer.OnNext(false);
-                                _parent._observer.OnCompleted();
-                                _parent.Dispose();
-                            }
-                            else if (_parent._doner)
+                            _parent._donel = true;
+                            if (_parent._ql.Count == 0)
                             {
-                                _parent._observer.OnNext(true);
-                                _parent._observer.OnCompleted();
-                                _parent.Dispose();
+                                if (_parent._qr.Count > 0)
+                                {
+                                    _parent._observer.OnNext(false);
+                                    _parent._observer.OnCompleted();
+                                    _parent.Dispose();
+                                }
+                                else if (_parent._doner)
+                                {
+                                    _parent._observer.OnNext(true);
+                                    _parent._observer.OnCompleted();
+                                    _parent.Dispose();
+                                }
                             }
                         }
                     }
                 }
-            }
-
-            class S : IObserver<TSource>
-            {
-                private readonly _ _parent;
 
-                public S(_ parent)
+                private sealed class SecondObserver : IObserver<TSource>
                 {
-                    _parent = parent;
-                }
+                    private readonly _ _parent;
 
-                public void OnNext(TSource value)
-                {
-                    lock (_parent._gate)
+                    public SecondObserver(_ parent)
+                    {
+                        _parent = parent;
+                    }
+
+                    public void OnNext(TSource value)
                     {
-                        if (_parent._ql.Count > 0)
+                        lock (_parent._gate)
                         {
-                            var equal = false;
-                            var v = _parent._ql.Dequeue();
-                            try
-                            {
-                                equal = _parent._parent._comparer.Equals(v, value);
-                            }
-                            catch (Exception exception)
+                            if (_parent._ql.Count > 0)
                             {
-                                _parent._observer.OnError(exception);
-                                _parent.Dispose();
-                                return;
+                                var equal = false;
+                                var v = _parent._ql.Dequeue();
+                                try
+                                {
+                                    equal = _parent._comparer.Equals(v, value);
+                                }
+                                catch (Exception exception)
+                                {
+                                    _parent._observer.OnError(exception);
+                                    _parent.Dispose();
+                                    return;
+                                }
+                                if (!equal)
+                                {
+                                    _parent._observer.OnNext(false);
+                                    _parent._observer.OnCompleted();
+                                    _parent.Dispose();
+                                }
                             }
-                            if (!equal)
+                            else if (_parent._donel)
                             {
                                 _parent._observer.OnNext(false);
                                 _parent._observer.OnCompleted();
                                 _parent.Dispose();
                             }
+                            else
+                                _parent._qr.Enqueue(value);
                         }
-                        else if (_parent._donel)
-                        {
-                            _parent._observer.OnNext(false);
-                            _parent._observer.OnCompleted();
-                            _parent.Dispose();
-                        }
-                        else
-                            _parent._qr.Enqueue(value);
                     }
-                }
 
-                public void OnError(Exception error)
-                {
-                    lock (_parent._gate)
+                    public void OnError(Exception error)
                     {
-                        _parent._observer.OnError(error);
-                        _parent.Dispose();
+                        lock (_parent._gate)
+                        {
+                            _parent._observer.OnError(error);
+                            _parent.Dispose();
+                        }
                     }
-                }
 
-                public void OnCompleted()
-                {
-                    lock (_parent._gate)
+                    public void OnCompleted()
                     {
-                        _parent._doner = true;
-                        if (_parent._qr.Count == 0)
+                        lock (_parent._gate)
                         {
-                            if (_parent._ql.Count > 0)
-                            {
-                                _parent._observer.OnNext(false);
-                                _parent._observer.OnCompleted();
-                                _parent.Dispose();
-                            }
-                            else if (_parent._donel)
+                            _parent._doner = true;
+                            if (_parent._qr.Count == 0)
                             {
-                                _parent._observer.OnNext(true);
-                                _parent._observer.OnCompleted();
-                                _parent.Dispose();
+                                if (_parent._ql.Count > 0)
+                                {
+                                    _parent._observer.OnNext(false);
+                                    _parent._observer.OnCompleted();
+                                    _parent.Dispose();
+                                }
+                                else if (_parent._donel)
+                                {
+                                    _parent._observer.OnNext(true);
+                                    _parent._observer.OnCompleted();
+                                    _parent.Dispose();
+                                }
                             }
                         }
                     }
@@ -232,95 +218,116 @@ namespace System.Reactive.Linq.ObservableImpl
             }
         }
 
-        class SequenceEqualImpl : Sink<bool>, IObserver<TSource>
+        internal sealed class Enumerable : Producer<bool>
         {
-            private readonly SequenceEqual<TSource> _parent;
+            private readonly IObservable<TSource> _first;
+            private readonly IEnumerable<TSource> _second;
+            private readonly IEqualityComparer<TSource> _comparer;
 
-            public SequenceEqualImpl(SequenceEqual<TSource> parent, IObserver<bool> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Enumerable(IObservable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
             {
-                _parent = parent;
+                _first = first;
+                _second = second;
+                _comparer = comparer;
             }
 
-            private IEnumerator<TSource> _enumerator;
+            protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_comparer, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
+            }
 
-            public IDisposable Run()
+            private sealed class _ : Sink<bool>, IObserver<TSource>
             {
-                //
-                // Notice the evaluation order of obtaining the enumerator and subscribing to the
-                // observable sequence is reversed compared to the operator's signature. This is
-                // required to make sure the enumerator is available as soon as the observer can
-                // be called. Otherwise, we end up having a race for the initialization and use
-                // of the _rightEnumerator field.
-                //
-                try
-                {
-                    _enumerator = _parent._secondE.GetEnumerator();
-                }
-                catch (Exception exception)
+                private readonly IEqualityComparer<TSource> _comparer;
+
+                public _(IEqualityComparer<TSource> comparer, IObserver<bool> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnError(exception);
-                    base.Dispose();
-                    return Disposable.Empty;
+                    _comparer = comparer;
                 }
 
-                return StableCompositeDisposable.Create(
-                    _parent._first.SubscribeSafe(this),
-                    _enumerator
-                );
-            }
-
-            public void OnNext(TSource value)
-            {
-                var equal = false;
+                private IEnumerator<TSource> _enumerator;
 
-                try
+                public IDisposable Run(Enumerable parent)
                 {
-                    if (_enumerator.MoveNext())
+                    //
+                    // Notice the evaluation order of obtaining the enumerator and subscribing to the
+                    // observable sequence is reversed compared to the operator's signature. This is
+                    // required to make sure the enumerator is available as soon as the observer can
+                    // be called. Otherwise, we end up having a race for the initialization and use
+                    // of the _rightEnumerator field.
+                    //
+                    try
+                    {
+                        _enumerator = parent._second.GetEnumerator();
+                    }
+                    catch (Exception exception)
                     {
-                        var current = _enumerator.Current;
-                        equal = _parent._comparer.Equals(value, current);
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                        return Disposable.Empty;
                     }
+
+                    return StableCompositeDisposable.Create(
+                        parent._first.SubscribeSafe(this),
+                        _enumerator
+                    );
                 }
-                catch (Exception exception)
+
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnError(exception);
-                    base.Dispose();
-                    return;
+                    var equal = false;
+
+                    try
+                    {
+                        if (_enumerator.MoveNext())
+                        {
+                            var current = _enumerator.Current;
+                            equal = _comparer.Equals(value, current);
+                        }
+                    }
+                    catch (Exception exception)
+                    {
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                        return;
+                    }
+
+                    if (!equal)
+                    {
+                        base._observer.OnNext(false);
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
 
-                if (!equal)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnNext(false);
-                    base._observer.OnCompleted();
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public void OnCompleted()
+                {
+                    var hasNext = false;
 
-            public void OnCompleted()
-            {
-                var hasNext = false;
+                    try
+                    {
+                        hasNext = _enumerator.MoveNext();
+                    }
+                    catch (Exception exception)
+                    {
+                        base._observer.OnError(exception);
+                        base.Dispose();
+                        return;
+                    }
 
-                try
-                {
-                    hasNext = _enumerator.MoveNext();
-                }
-                catch (Exception exception)
-                {
-                    base._observer.OnError(exception);
+                    base._observer.OnNext(!hasNext);
+                    base._observer.OnCompleted();
                     base.Dispose();
-                    return;
                 }
-
-                base._observer.OnNext(!hasNext);
-                base._observer.OnCompleted();
-                base.Dispose();
             }
         }
     }

+ 101 - 95
Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs

@@ -4,148 +4,154 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class SingleAsync<TSource> : Producer<TSource>
+    internal static class SingleAsync<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-        private readonly bool _throwOnEmpty;
-
-        public SingleAsync(IObservable<TSource> source, Func<TSource, bool> predicate, bool throwOnEmpty)
+        internal sealed class Sequence : Producer<TSource>
         {
-            _source = source;
-            _predicate = predicate;
-            _throwOnEmpty = throwOnEmpty;
-        }
+            private readonly IObservable<TSource> _source;
 
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate != null)
+            public Sequence(IObservable<TSource> source)
             {
-                var sink = new SingleAsyncImpl(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new _(this, observer, cancel);
+                var sink = new _(observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
-
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly SingleAsync<TSource> _parent;
-            private TSource _value;
-            private bool _seenValue;
 
-            public _(SingleAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _parent = parent;
+                private TSource _value;
+                private bool _seenValue;
 
-                _value = default(TSource);
-                _seenValue = false;
-            }
-
-            public void OnNext(TSource value)
-            {
-                if (_seenValue)
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT));
-                    base.Dispose();
-                    return;
+                    _value = default(TSource);
+                    _seenValue = false;
                 }
 
-                _value = value;
-                _seenValue = true;
-            }
+                public void OnNext(TSource value)
+                {
+                    if (_seenValue)
+                    {
+                        base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT));
+                        base.Dispose();
+                        return;
+                    }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                    _value = value;
+                    _seenValue = true;
+                }
 
-            public void OnCompleted()
-            {
-                if (!_seenValue && _parent._throwOnEmpty)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+                    base._observer.OnError(error);
+                    base.Dispose();
                 }
-                else
+
+                public void OnCompleted()
                 {
-                    base._observer.OnNext(_value);
-                    base._observer.OnCompleted();
-                }
+                    if (!_seenValue)
+                    {
+                        base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+                    }
+                    else
+                    {
+                        base._observer.OnNext(_value);
+                        base._observer.OnCompleted();
+                    }
 
-                base.Dispose();
+                    base.Dispose();
+                }
             }
         }
 
-        class SingleAsyncImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Predicate : Producer<TSource>
         {
-            private readonly SingleAsync<TSource> _parent;
-            private TSource _value;
-            private bool _seenValue;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
 
-            public SingleAsyncImpl(SingleAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
             {
-                _parent = parent;
+                _source = source;
+                _predicate = predicate;
+            }
 
-                _value = default(TSource);
-                _seenValue = false;
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                var b = false;
+                private readonly Func<TSource, bool> _predicate;
+                private TSource _value;
+                private bool _seenValue;
 
-                try
-                {
-                    b = _parent._predicate(value);
-                }
-                catch (Exception ex)
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnError(ex);
-                    base.Dispose();
-                    return;
+                    _predicate = predicate;
+
+                    _value = default(TSource);
+                    _seenValue = false;
                 }
 
-                if (b)
+                public void OnNext(TSource value)
                 {
-                    if (_seenValue)
+                    var b = false;
+
+                    try
                     {
-                        base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_MATCHING_ELEMENT));
+                        b = _predicate(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
                         base.Dispose();
                         return;
                     }
 
-                    _value = value;
-                    _seenValue = true;
+                    if (b)
+                    {
+                        if (_seenValue)
+                        {
+                            base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_MATCHING_ELEMENT));
+                            base.Dispose();
+                            return;
+                        }
+
+                        _value = value;
+                        _seenValue = true;
+                    }
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
 
-            public void OnCompleted()
-            {
-                if (!_seenValue && _parent._throwOnEmpty)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+                    base._observer.OnError(error);
+                    base.Dispose();
                 }
-                else
+
+                public void OnCompleted()
                 {
-                    base._observer.OnNext(_value);
-                    base._observer.OnCompleted();
-                }
+                    if (!_seenValue)
+                    {
+                        base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+                    }
+                    else
+                    {
+                        base._observer.OnNext(_value);
+                        base._observer.OnCompleted();
+                    }
 
-                base.Dispose();
+                    base.Dispose();
+                }
             }
         }
     }

+ 142 - 0
Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs

@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+namespace System.Reactive.Linq.ObservableImpl
+{
+    internal static class SingleOrDefaultAsync<TSource>
+    {
+        internal sealed class Sequence : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+
+            public Sequence(IObservable<TSource> source)
+            {
+                _source = source;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                private TSource _value;
+                private bool _seenValue;
+
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _value = default(TSource);
+                    _seenValue = false;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    if (_seenValue)
+                    {
+                        base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT));
+                        base.Dispose();
+                        return;
+                    }
+
+                    _value = value;
+                    _seenValue = true;
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_value);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+
+        internal sealed class Predicate : Producer<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
+
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                private readonly Func<TSource, bool> _predicate;
+                private TSource _value;
+                private bool _seenValue;
+
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _predicate = predicate;
+
+                    _value = default(TSource);
+                    _seenValue = false;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    var b = false;
+
+                    try
+                    {
+                        b = _predicate(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        base._observer.OnError(ex);
+                        base.Dispose();
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        if (_seenValue)
+                        {
+                            base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_MATCHING_ELEMENT));
+                            base.Dispose();
+                            return;
+                        }
+
+                        _value = value;
+                        _seenValue = true;
+                    }
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnNext(_value);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+            }
+        }
+    }
+}

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

@@ -7,143 +7,145 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Skip<TSource> : Producer<TSource>
+    internal static class Skip<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly int _count;
-        private readonly TimeSpan _duration;
-        internal readonly IScheduler _scheduler;
-
-        public Skip(IObservable<TSource> source, int count)
-        {
-            _source = source;
-            _count = count;
-        }
-
-        public Skip(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
-        {
-            _source = source;
-            _duration = duration;
-            _scheduler = scheduler;
-        }
-
-        public IObservable<TSource> Combine(int count)
-        {
-            //
-            // Sum semantics:
-            //
-            //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
-            //   xs.Skip(2)            --x--x--o--o--o--o--|      xs.Skip(3)            --x--x--x--o--o--o--|
-            //   xs.Skip(2).Skip(3)    --------x--x--x--o--|      xs.Skip(3).Skip(2)    -----------x--x--o--|
-            //
-            return new Skip<TSource>(_source, _count + count);
-        }
-
-        public IObservable<TSource> Combine(TimeSpan duration)
-        {
-            //
-            // Maximum semantics:
-            //
-            //   t                     0--1--2--3--4--5--6--7->   t                     0--1--2--3--4--5--6--7->
-            //                                                    
-            //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
-            //   xs.Skip(2s)           xxxxxxx-o--o--o--o--|      xs.Skip(3s)           xxxxxxxxxx-o--o--o--|
-            //   xs.Skip(2s).Skip(3s)  xxxxxxxxxx-o--o--o--|      xs.Skip(3s).Skip(2s)  xxxxxxx----o--o--o--|
-            //
-            if (duration <= _duration)
-                return this;
-            else
-                return new Skip<TSource>(_source, duration, _scheduler);
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_scheduler == null)
-            {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
-            }
-            else
-            {
-                var sink = new SkipImpl(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
-            }
-        }
-
-        class _ : Sink<TSource>, IObserver<TSource>
+        internal sealed class Count : Producer<TSource>
         {
-            private readonly Skip<TSource> _parent;
-            private int _remaining;
+            private readonly IObservable<TSource> _source;
+            private readonly int _count;
 
-            public _(Skip<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Count(IObservable<TSource> source, int count)
             {
-                _parent = parent;
-                _remaining = _parent._count;
+                _source = source;
+                _count = count;
             }
 
-            public void OnNext(TSource value)
+            public IObservable<TSource> Combine(int count)
             {
-                if (_remaining <= 0)
-                    base._observer.OnNext(value);
-                else
-                    _remaining--;
+                //
+                // Sum semantics:
+                //
+                //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
+                //   xs.Skip(2)            --x--x--o--o--o--o--|      xs.Skip(3)            --x--x--x--o--o--o--|
+                //   xs.Skip(2).Skip(3)    --------x--x--x--o--|      xs.Skip(3).Skip(2)    -----------x--x--o--|
+                //
+                return new Count(_source, _count + count);
             }
 
-            public void OnError(Exception error)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                base._observer.OnError(error);
-                base.Dispose();
+                var sink = new _(_count, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnCompleted()
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                base._observer.OnCompleted();
-                base.Dispose();
+                private int _remaining;
+
+                public _(int count, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _remaining = count;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    if (_remaining <= 0)
+                        base._observer.OnNext(value);
+                    else
+                        _remaining--;
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class SkipImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Time : Producer<TSource>
         {
-            private readonly Skip<TSource> _parent;
-            private volatile bool _open;
+            private readonly IObservable<TSource> _source;
+            private readonly TimeSpan _duration;
+            internal readonly IScheduler _scheduler;
 
-            public SkipImpl(Skip<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Time(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
             {
-                _parent = parent;
+                _source = source;
+                _duration = duration;
+                _scheduler = scheduler;
             }
 
-            public IDisposable Run()
+            public IObservable<TSource> Combine(TimeSpan duration)
             {
-                var t = _parent._scheduler.Schedule(_parent._duration, Tick);
-                var d = _parent._source.SubscribeSafe(this);
-                return StableCompositeDisposable.Create(t, d);
-            }
-
-            private void Tick()
-            {
-                _open = true;
-            }
-
-            public void OnNext(TSource value)
-            {
-                if (_open)
-                    base._observer.OnNext(value);
+                //
+                // Maximum semantics:
+                //
+                //   t                     0--1--2--3--4--5--6--7->   t                     0--1--2--3--4--5--6--7->
+                //                                                    
+                //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
+                //   xs.Skip(2s)           xxxxxxx-o--o--o--o--|      xs.Skip(3s)           xxxxxxxxxx-o--o--o--|
+                //   xs.Skip(2s).Skip(3s)  xxxxxxxxxx-o--o--o--|      xs.Skip(3s).Skip(2s)  xxxxxxx----o--o--o--|
+                //
+                if (duration <= _duration)
+                    return this;
+                else
+                    return new Time(_source, duration, _scheduler);
             }
 
-            public void OnError(Exception error)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                base._observer.OnError(error);
-                base.Dispose();
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            public void OnCompleted()
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                base._observer.OnCompleted();
-                base.Dispose();
+                private volatile bool _open;
+
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                }
+
+                public IDisposable Run(Time parent)
+                {
+                    var t = parent._scheduler.Schedule(parent._duration, Tick);
+                    var d = parent._source.SubscribeSafe(this);
+                    return StableCompositeDisposable.Create(t, d);
+                }
+
+                private void Tick()
+                {
+                    _open = true;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    if (_open)
+                        base._observer.OnNext(value);
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

+ 95 - 89
Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipLast.cs

@@ -7,117 +7,123 @@ using System.Reactive.Concurrency;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class SkipLast<TSource> : Producer<TSource>
+    internal static class SkipLast<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly int _count;
-        private readonly TimeSpan _duration;
-        private readonly IScheduler _scheduler;
-
-        public SkipLast(IObservable<TSource> source, int count)
-        {
-            _source = source;
-            _count = count;
-        }
-
-        public SkipLast(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
-        {
-            _source = source;
-            _duration = duration;
-            _scheduler = scheduler;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_scheduler == null)
-            {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
-            }
-            else
-            {
-                var sink = new SkipLastImpl(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
-            }
-        }
-
-        class _ : Sink<TSource>, IObserver<TSource>
+        internal sealed class Count : Producer<TSource>
         {
-            private readonly SkipLast<TSource> _parent;
-            private Queue<TSource> _queue;
-
-            public _(SkipLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
-                _queue = new Queue<TSource>();
-            }
+            private readonly IObservable<TSource> _source;
+            private readonly int _count;
 
-            public void OnNext(TSource value)
+            public Count(IObservable<TSource> source, int count)
             {
-                _queue.Enqueue(value);
-                if (_queue.Count > _parent._count)
-                    base._observer.OnNext(_queue.Dequeue());
+                _source = source;
+                _count = count;
             }
 
-            public void OnError(Exception error)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                base._observer.OnError(error);
-                base.Dispose();
+                var sink = new _(_count, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnCompleted()
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                base._observer.OnCompleted();
-                base.Dispose();
+                private int _count;
+                private Queue<TSource> _queue;
+
+                public _(int count, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _count = count;
+                    _queue = new Queue<TSource>();
+                }
+
+                public void OnNext(TSource value)
+                {
+                    _queue.Enqueue(value);
+                    if (_queue.Count > _count)
+                        base._observer.OnNext(_queue.Dequeue());
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class SkipLastImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Time : Producer<TSource>
         {
-            private readonly SkipLast<TSource> _parent;
-            private Queue<System.Reactive.TimeInterval<TSource>> _queue;
-
-            public SkipLastImpl(SkipLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
-                _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
-            }
-
-            private IStopwatch _watch;
-
-            public IDisposable Run()
-            {
-                _watch = _parent._scheduler.StartStopwatch();
+            private readonly IObservable<TSource> _source;
+            private readonly TimeSpan _duration;
+            private readonly IScheduler _scheduler;
 
-                return _parent._source.SubscribeSafe(this);
-            }
-
-            public void OnNext(TSource value)
+            public Time(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
             {
-                var now = _watch.Elapsed;
-                _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
-                while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration)
-                    base._observer.OnNext(_queue.Dequeue().Value);
+                _source = source;
+                _duration = duration;
+                _scheduler = scheduler;
             }
 
-            public void OnError(Exception error)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                base._observer.OnError(error);
-                base.Dispose();
+                var sink = new _(_duration, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            public void OnCompleted()
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                var now = _watch.Elapsed;
-                while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration)
-                    base._observer.OnNext(_queue.Dequeue().Value);
-
-                base._observer.OnCompleted();
-                base.Dispose();
+                private readonly TimeSpan _duration;
+                private Queue<System.Reactive.TimeInterval<TSource>> _queue;
+
+                public _(TimeSpan duration, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _duration = duration;
+                    _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+                }
+
+                private IStopwatch _watch;
+
+                public IDisposable Run(Time parent)
+                {
+                    _watch = parent._scheduler.StartStopwatch();
+
+                    return parent._source.SubscribeSafe(this);
+                }
+
+                public void OnNext(TSource value)
+                {
+                    var now = _watch.Elapsed;
+                    _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
+                    while (_queue.Count > 0 && now - _queue.Peek().Interval >= _duration)
+                        base._observer.OnNext(_queue.Dequeue().Value);
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    var now = _watch.Elapsed;
+                    while (_queue.Count > 0 && now - _queue.Peek().Interval >= _duration)
+                        base._observer.OnNext(_queue.Dequeue().Value);
+
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

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

@@ -20,28 +20,25 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>
+        private sealed class _ : Sink<TSource>
         {
-            private readonly SkipUntil<TSource, TOther> _parent;
-
-            public _(SkipUntil<TSource, TOther> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(SkipUntil<TSource, TOther> parent)
             {
-                var sourceObserver = new T(this);
-                var otherObserver = new O(this, sourceObserver);
+                var sourceObserver = new SourceObserver(this);
+                var otherObserver = new OtherObserver(this, sourceObserver);
 
-                var sourceSubscription = _parent._source.SubscribeSafe(sourceObserver);
-                var otherSubscription = _parent._other.SubscribeSafe(otherObserver);
+                var sourceSubscription = parent._source.SubscribeSafe(sourceObserver);
+                var otherSubscription = parent._other.SubscribeSafe(otherObserver);
 
                 sourceObserver.Disposable = sourceSubscription;
                 otherObserver.Disposable = otherSubscription;
@@ -52,13 +49,13 @@ namespace System.Reactive.Linq.ObservableImpl
                 );
             }
 
-            class T : IObserver<TSource>
+            private sealed class SourceObserver : IObserver<TSource>
             {
                 private readonly _ _parent;
                 public volatile IObserver<TSource> _observer;
                 private readonly SingleAssignmentDisposable _subscription;
 
-                public T(_ parent)
+                public SourceObserver(_ parent)
                 {
                     _parent = parent;
                     _observer = NopObserver<TSource>.Instance;
@@ -88,13 +85,13 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class O : IObserver<TOther>
+            private sealed class OtherObserver : IObserver<TOther>
             {
                 private readonly _ _parent;
-                private readonly T _sourceObserver;
+                private readonly SourceObserver _sourceObserver;
                 private readonly SingleAssignmentDisposable _subscription;
 
-                public O(_ parent, T sourceObserver)
+                public OtherObserver(_ parent, SourceObserver sourceObserver)
                 {
                     _parent = parent;
                     _sourceObserver = sourceObserver;
@@ -158,26 +155,24 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly SkipUntil<TSource> _parent;
             private volatile bool _open;
 
-            public _(SkipUntil<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(SkipUntil<TSource> parent)
             {
-                var t = _parent._scheduler.Schedule(_parent._startTime, Tick);
-                var d = _parent._source.SubscribeSafe(this);
+                var t = parent._scheduler.Schedule(parent._startTime, Tick);
+                var d = parent._source.SubscribeSafe(this);
                 return StableCompositeDisposable.Create(t, d);
             }
 

+ 102 - 86
Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipWhile.cs

@@ -4,133 +4,149 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class SkipWhile<TSource> : Producer<TSource>
+    internal static class SkipWhile<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-        private readonly Func<TSource, int, bool> _predicateI;
-
-        public SkipWhile(IObservable<TSource> source, Func<TSource, bool> predicate)
+        internal sealed class Predicate : Producer<TSource>
         {
-            _source = source;
-            _predicate = predicate;
-        }
-
-        public SkipWhile(IObservable<TSource> source, Func<TSource, int, bool> predicate)
-        {
-            _source = source;
-            _predicateI = predicate;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
 
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate != null)
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
+                _predicate = predicate;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new SkipWhileImpl(this, observer, cancel);
+                var sink = new _(_predicate, observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
 
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly SkipWhile<TSource> _parent;
-            private bool _running;
-
-            public _(SkipWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _parent = parent;
-                _running = false;
-            }
+                private Func<TSource, bool> _predicate;
 
-            public void OnNext(TSource value)
-            {
-                if (!_running)
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _predicate = predicate;
+                }
+
+                public void OnNext(TSource value)
                 {
-                    try
+                    if (_predicate != null)
                     {
-                        _running = !_parent._predicate(value);
+                        var shouldStart = default(bool);
+                        try
+                        {
+                            shouldStart = !_predicate(value);
+                        }
+                        catch (Exception exception)
+                        {
+                            base._observer.OnError(exception);
+                            base.Dispose();
+                            return;
+                        }
+
+                        if (shouldStart)
+                        {
+                            _predicate = null;
+
+                            base._observer.OnNext(value);
+                        }
                     }
-                    catch (Exception exception)
+                    else
                     {
-                        base._observer.OnError(exception);
-                        base.Dispose();
-                        return;
+                        base._observer.OnNext(value);
                     }
                 }
 
-                if (_running)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnNext(value);
+                    base._observer.OnError(error);
+                    base.Dispose();
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
 
-            public void OnCompleted()
-            {
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class SkipWhileImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class PredicateIndexed : Producer<TSource>
         {
-            private readonly SkipWhile<TSource> _parent;
-            private bool _running;
-            private int _index;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, int, bool> _predicate;
+
+            public PredicateIndexed(IObservable<TSource> source, Func<TSource, int, bool> predicate)
+            {
+                _source = source;
+                _predicate = predicate;
+            }
 
-            public SkipWhileImpl(SkipWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _parent = parent;
-                _running = false;
-                _index = 0;
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                if (!_running)
+                private Func<TSource, int, bool> _predicate;
+                private int _index;
+
+                public _(Func<TSource, int, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    try
+                    _predicate = predicate;
+                    _index = 0;
+                }
+
+                public void OnNext(TSource value)
+                {
+                    if (_predicate != null)
                     {
-                        _running = !_parent._predicateI(value, checked(_index++));
+                        var shouldStart = default(bool);
+                        try
+                        {
+                            shouldStart = !_predicate(value, checked(_index++));
+                        }
+                        catch (Exception exception)
+                        {
+                            base._observer.OnError(exception);
+                            base.Dispose();
+                            return;
+                        }
+
+                        if (shouldStart)
+                        {
+                            _predicate = null;
+
+                            base._observer.OnNext(value);
+                        }
                     }
-                    catch (Exception exception)
+                    else
                     {
-                        base._observer.OnError(exception);
-                        base.Dispose();
-                        return;
+                        base._observer.OnNext(value);
                     }
                 }
 
-                if (_running)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnNext(value);
+                    base._observer.OnError(error);
+                    base.Dispose();
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
 
-            public void OnCompleted()
-            {
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

+ 10 - 10
Rx.NET/Source/src/System.Reactive/Linq/Observable/Sum.cs

@@ -20,7 +20,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double>, IObserver<double>
+        private sealed class _ : Sink<double>, IObserver<double>
         {
             private double _sum;
 
@@ -66,7 +66,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float>, IObserver<float>
+        private sealed class _ : Sink<float>, IObserver<float>
         {
             private double _sum; // This is what LINQ to Objects does!
 
@@ -112,7 +112,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal>, IObserver<decimal>
+        private sealed class _ : Sink<decimal>, IObserver<decimal>
         {
             private decimal _sum;
 
@@ -158,7 +158,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<int>, IObserver<int>
+        private sealed class _ : Sink<int>, IObserver<int>
         {
             private int _sum;
 
@@ -215,7 +215,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<long>, IObserver<long>
+        private sealed class _ : Sink<long>, IObserver<long>
         {
             private long _sum;
 
@@ -272,7 +272,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<double?>, IObserver<double?>
+        private sealed class _ : Sink<double?>, IObserver<double?>
         {
             private double _sum;
 
@@ -319,7 +319,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<float?>, IObserver<float?>
+        private sealed class _ : Sink<float?>, IObserver<float?>
         {
             private double _sum; // This is what LINQ to Objects does!
 
@@ -366,7 +366,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<decimal?>, IObserver<decimal?>
+        private sealed class _ : Sink<decimal?>, IObserver<decimal?>
         {
             private decimal _sum;
 
@@ -413,7 +413,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<int?>, IObserver<int?>
+        private sealed class _ : Sink<int?>, IObserver<int?>
         {
             private int _sum;
 
@@ -471,7 +471,7 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<long?>, IObserver<long?>
+        private sealed class _ : Sink<long?>, IObserver<long?>
         {
             private long _sum;
 

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

@@ -17,31 +17,28 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<IObservable<TSource>>
+        private sealed class _ : Sink<TSource>, IObserver<IObservable<TSource>>
         {
-            private readonly Switch<TSource> _parent;
+            private readonly object _gate = new object();
 
-            public _(Switch<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            private object _gate;
             private IDisposable _subscription;
             private SerialDisposable _innerSubscription;
             private bool _isStopped;
             private ulong _latest;
             private bool _hasLatest;
 
-            public IDisposable Run()
+            public IDisposable Run(Switch<TSource> parent)
             {
-                _gate = new object();
                 _innerSubscription = new SerialDisposable();
                 _isStopped = false;
                 _latest = 0UL;
@@ -49,7 +46,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 var subscription = new SingleAssignmentDisposable();
                 _subscription = subscription;
-                subscription.Disposable = _parent._sources.SubscribeSafe(this);
+                subscription.Disposable = parent._sources.SubscribeSafe(this);
 
                 return StableCompositeDisposable.Create(_subscription, _innerSubscription);
             }
@@ -65,7 +62,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 var d = new SingleAssignmentDisposable();
                 _innerSubscription.Disposable = d;
-                d.Disposable = value.SubscribeSafe(new Iter(this, id, d));
+                d.Disposable = value.SubscribeSafe(new InnerObserver(this, id, d));
             }
 
             public void OnError(Exception error)
@@ -91,13 +88,13 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class Iter : IObserver<TSource>
+            private sealed class InnerObserver : IObserver<TSource>
             {
                 private readonly _ _parent;
                 private readonly ulong _id;
                 private readonly IDisposable _self;
 
-                public Iter(_ parent, ulong id, IDisposable self)
+                public InnerObserver(_ parent, ulong id, IDisposable self)
                 {
                     _parent = parent;
                     _id = id;
@@ -109,7 +106,9 @@ namespace System.Reactive.Linq.ObservableImpl
                     lock (_parent._gate)
                     {
                         if (_parent._latest == _id)
+                        {
                             _parent._observer.OnNext(value);
+                        }
                     }
                 }
 

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

@@ -22,21 +22,19 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_gate, observer, cancel);
             setSink(sink);
             return _source.Subscribe(sink);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Synchronize<TSource> _parent;
-            private object _gate;
+            private readonly object _gate;
 
-            public _(Synchronize<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(object gate, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _gate = _parent._gate ?? new object();
+                _gate = gate ?? new object();
             }
 
             public void OnNext(TSource value)

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

@@ -7,167 +7,168 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Take<TSource> : Producer<TSource>
+    internal static class Take<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly int _count;
-        private readonly TimeSpan _duration;
-        internal readonly IScheduler _scheduler;
-
-        public Take(IObservable<TSource> source, int count)
-        {
-            _source = source;
-            _count = count;
-        }
-
-        public Take(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
-        {
-            _source = source;
-            _duration = duration;
-            _scheduler = scheduler;
-        }
-
-        public IObservable<TSource> Combine(int count)
+        internal sealed class Count : Producer<TSource>
         {
-            //
-            // Minimum semantics:
-            //
-            //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
-            //   xs.Take(5)            --o--o--o--o--o|           xs.Take(3)            --o--o--o|
-            //   xs.Take(5).Take(3)    --o--o--o|                 xs.Take(3).Take(5)    --o--o--o|
-            //
-            if (_count <= count)
-                return this;
-            else
-                return new Take<TSource>(_source, count);
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly int _count;
 
-        public IObservable<TSource> Combine(TimeSpan duration)
-        {
-            //
-            // Minimum semantics:
-            //
-            //   t                     0--1--2--3--4--5--6--7->   t                     0--1--2--3--4--5--6--7->
-            //                                                    
-            //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
-            //   xs.Take(5s)           --o--o--o--o--o|           xs.Take(3s)           --o--o--o|
-            //   xs.Take(5s).Take(3s)  --o--o--o|                 xs.Take(3s).Take(5s)  --o--o--o|
-            //
-            if (_duration <= duration)
-                return this;
-            else
-                return new Take<TSource>(_source, duration, _scheduler);
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_scheduler == null)
+            public Count(IObservable<TSource> source, int count)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
+                _count = count;
             }
-            else
+
+            public IObservable<TSource> Combine(int count)
             {
-                var sink = new TakeImpl(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                //
+                // Minimum semantics:
+                //
+                //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
+                //   xs.Take(5)            --o--o--o--o--o|           xs.Take(3)            --o--o--o|
+                //   xs.Take(5).Take(3)    --o--o--o|                 xs.Take(3).Take(5)    --o--o--o|
+                //
+                if (_count <= count)
+                    return this;
+                else
+                    return new Count(_source, count);
             }
-        }
-
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly Take<TSource> _parent;
-            private int _remaining;
 
-            public _(Take<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _parent = parent;
-                _remaining = _parent._count;
+                var sink = new _(_count, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                if (_remaining > 0)
+                private int _remaining;
+
+                public _(int count, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    --_remaining;
-                    base._observer.OnNext(value);
+                    _remaining = count;
+                }
 
-                    if (_remaining == 0)
+                public void OnNext(TSource value)
+                {
+                    if (_remaining > 0)
                     {
-                        base._observer.OnCompleted();
-                        base.Dispose();
+                        --_remaining;
+                        base._observer.OnNext(value);
+
+                        if (_remaining == 0)
+                        {
+                            base._observer.OnCompleted();
+                            base.Dispose();
+                        }
                     }
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
 
-            public void OnCompleted()
-            {
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class TakeImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Time : Producer<TSource>
         {
-            private readonly Take<TSource> _parent;
+            private readonly IObservable<TSource> _source;
+            private readonly TimeSpan _duration;
+            internal readonly IScheduler _scheduler;
 
-            public TakeImpl(Take<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Time(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
             {
-                _parent = parent;
+                _source = source;
+                _duration = duration;
+                _scheduler = scheduler;
             }
 
-            private object _gate;
-
-            public IDisposable Run()
+            public IObservable<TSource> Combine(TimeSpan duration)
             {
-                _gate = new object();
+                //
+                // Minimum semantics:
+                //
+                //   t                     0--1--2--3--4--5--6--7->   t                     0--1--2--3--4--5--6--7->
+                //                                                    
+                //   xs                    --o--o--o--o--o--o--|      xs                    --o--o--o--o--o--o--|
+                //   xs.Take(5s)           --o--o--o--o--o|           xs.Take(3s)           --o--o--o|
+                //   xs.Take(5s).Take(3s)  --o--o--o|                 xs.Take(3s).Take(5s)  --o--o--o|
+                //
+                if (_duration <= duration)
+                    return this;
+                else
+                    return new Time(_source, duration, _scheduler);
+            }
 
-                var t = _parent._scheduler.Schedule(_parent._duration, Tick);
-                var d = _parent._source.SubscribeSafe(this);
-                return StableCompositeDisposable.Create(t, d);
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            private void Tick()
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                lock (_gate)
+                public _(IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnCompleted();
-                    base.Dispose();
                 }
-            }
 
-            public void OnNext(TSource value)
-            {
-                lock (_gate)
+                private object _gate;
+
+                public IDisposable Run(Time parent)
                 {
-                    base._observer.OnNext(value);
+                    _gate = new object();
+
+                    var t = parent._scheduler.Schedule(parent._duration, Tick);
+                    var d = parent._source.SubscribeSafe(this);
+                    return StableCompositeDisposable.Create(t, d);
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                lock (_gate)
+                private void Tick()
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
-            }
 
-            public void OnCompleted()
-            {
-                lock (_gate)
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                    lock (_gate)
+                    {
+                        base._observer.OnNext(value);
+                    }
+                }
+
+                public void OnError(Exception error)
+                {
+                    lock (_gate)
+                    {
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
+                }
+
+                public void OnCompleted()
+                {
+                    lock (_gate)
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
             }
         }

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

@@ -8,221 +8,232 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class TakeLast<TSource> : Producer<TSource>
+    internal static class TakeLast<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly int _count;
-        private readonly TimeSpan _duration;
-        private readonly IScheduler _scheduler;
-        private readonly IScheduler _loopScheduler;
-
-        public TakeLast(IObservable<TSource> source, int count, IScheduler loopScheduler)
-        {
-            _source = source;
-            _count = count;
-            _loopScheduler = loopScheduler;
-        }
-
-        public TakeLast(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler, IScheduler loopScheduler)
+        internal sealed class Count : Producer<TSource>
         {
-            _source = source;
-            _duration = duration;
-            _scheduler = scheduler;
-            _loopScheduler = loopScheduler;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly int _count;
+            private readonly IScheduler _loopScheduler;
 
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_scheduler == null)
+            public Count(IObservable<TSource> source, int count, IScheduler loopScheduler)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _source = source;
+                _count = count;
+                _loopScheduler = loopScheduler;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new TakeLastImpl(this, observer, cancel);
+                var sink = new _(this, observer, cancel);
                 setSink(sink);
                 return sink.Run();
             }
-        }
 
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly TakeLast<TSource> _parent;
-            private Queue<TSource> _queue;
-
-            public _(TakeLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _parent = parent;
-                _queue = new Queue<TSource>();
-            }
+                // CONSIDER: This sink has a parent reference that can be considered for removal.
 
-            private SingleAssignmentDisposable _subscription;
-            private SingleAssignmentDisposable _loop;
+                private readonly Count _parent;
+                private Queue<TSource> _queue;
 
-            public IDisposable Run()
-            {
-                _subscription = new SingleAssignmentDisposable();
-                _loop = new SingleAssignmentDisposable();
-
-                _subscription.Disposable = _parent._source.SubscribeSafe(this);
-                
-                return StableCompositeDisposable.Create(_subscription, _loop);
-            }
+                public _(Count parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _parent = parent;
+                    _queue = new Queue<TSource>();
+                }
 
-            public void OnNext(TSource value)
-            {
-                _queue.Enqueue(value);
-                if (_queue.Count > _parent._count)
-                    _queue.Dequeue();
-            }
+                private SingleAssignmentDisposable _subscription;
+                private SingleAssignmentDisposable _loop;
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public IDisposable Run()
+                {
+                    _subscription = new SingleAssignmentDisposable();
+                    _loop = new SingleAssignmentDisposable();
 
-            public void OnCompleted()
-            {
-                _subscription.Dispose();
+                    _subscription.Disposable = _parent._source.SubscribeSafe(this);
 
-                var longRunning = _parent._loopScheduler.AsLongRunning();
-                if (longRunning != null)
-                    _loop.Disposable = longRunning.ScheduleLongRunning(Loop);
-                else
-                    _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec);
-            }
+                    return StableCompositeDisposable.Create(_subscription, _loop);
+                }
 
-            private void LoopRec(Action recurse)
-            {
-                if (_queue.Count > 0)
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnNext(_queue.Dequeue());
-                    recurse();
+                    _queue.Enqueue(value);
+                    if (_queue.Count > _parent._count)
+                        _queue.Dequeue();
                 }
-                else
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnCompleted();
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
 
-            private void Loop(ICancelable cancel)
-            {
-                var n = _queue.Count;
+                public void OnCompleted()
+                {
+                    _subscription.Dispose();
+
+                    var longRunning = _parent._loopScheduler.AsLongRunning();
+                    if (longRunning != null)
+                        _loop.Disposable = longRunning.ScheduleLongRunning(Loop);
+                    else
+                        _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec);
+                }
 
-                while (!cancel.IsDisposed)
+                private void LoopRec(Action recurse)
                 {
-                    if (n == 0)
+                    if (_queue.Count > 0)
                     {
-                        base._observer.OnCompleted();
-                        break;
+                        base._observer.OnNext(_queue.Dequeue());
+                        recurse();
                     }
                     else
-                        base._observer.OnNext(_queue.Dequeue());
-
-                    n--;
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
 
-                base.Dispose();
+                private void Loop(ICancelable cancel)
+                {
+                    var n = _queue.Count;
+
+                    while (!cancel.IsDisposed)
+                    {
+                        if (n == 0)
+                        {
+                            base._observer.OnCompleted();
+                            break;
+                        }
+                        else
+                            base._observer.OnNext(_queue.Dequeue());
+
+                        n--;
+                    }
+
+                    base.Dispose();
+                }
             }
         }
 
-        class TakeLastImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class Time : Producer<TSource>
         {
-            private readonly TakeLast<TSource> _parent;
-            private Queue<System.Reactive.TimeInterval<TSource>> _queue;
+            private readonly IObservable<TSource> _source;
+            private readonly TimeSpan _duration;
+            private readonly IScheduler _scheduler;
+            private readonly IScheduler _loopScheduler;
 
-            public TakeLastImpl(TakeLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Time(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler, IScheduler loopScheduler)
             {
-                _parent = parent;
-                _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+                _source = source;
+                _duration = duration;
+                _scheduler = scheduler;
+                _loopScheduler = loopScheduler;
             }
 
-            private SingleAssignmentDisposable _subscription;
-            private SingleAssignmentDisposable _loop;
-            private IStopwatch _watch;
-
-            public IDisposable Run()
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _subscription = new SingleAssignmentDisposable();
-                _loop = new SingleAssignmentDisposable();
-
-                _watch = _parent._scheduler.StartStopwatch();
-                _subscription.Disposable = _parent._source.SubscribeSafe(this);
-
-                return StableCompositeDisposable.Create(_subscription, _loop);
+                var sink = new _(this, observer, cancel);
+                setSink(sink);
+                return sink.Run();
             }
 
-            public void OnNext(TSource value)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                var now = _watch.Elapsed;
-                _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
-                Trim(now);
-            }
+                // CONSIDER: This sink has a parent reference that can be considered for removal.
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                private readonly Time _parent;
+                private Queue<System.Reactive.TimeInterval<TSource>> _queue;
 
-            public void OnCompleted()
-            {
-                _subscription.Dispose();
+                public _(Time parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _parent = parent;
+                    _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+                }
 
-                var now = _watch.Elapsed;
-                Trim(now);
+                private SingleAssignmentDisposable _subscription;
+                private SingleAssignmentDisposable _loop;
+                private IStopwatch _watch;
 
-                var longRunning = _parent._loopScheduler.AsLongRunning();
-                if (longRunning != null)
-                    _loop.Disposable = longRunning.ScheduleLongRunning(Loop);
-                else
-                    _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec);
-            }
+                public IDisposable Run()
+                {
+                    _subscription = new SingleAssignmentDisposable();
+                    _loop = new SingleAssignmentDisposable();
 
-            private void LoopRec(Action recurse)
-            {
-                if (_queue.Count > 0)
+                    _watch = _parent._scheduler.StartStopwatch();
+                    _subscription.Disposable = _parent._source.SubscribeSafe(this);
+
+                    return StableCompositeDisposable.Create(_subscription, _loop);
+                }
+
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnNext(_queue.Dequeue().Value);
-                    recurse();
+                    var now = _watch.Elapsed;
+                    _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
+                    Trim(now);
                 }
-                else
+
+                public void OnError(Exception error)
                 {
-                    base._observer.OnCompleted();
+                    base._observer.OnError(error);
                     base.Dispose();
                 }
-            }
 
-            private void Loop(ICancelable cancel)
-            {
-                var n = _queue.Count;
+                public void OnCompleted()
+                {
+                    _subscription.Dispose();
+
+                    var now = _watch.Elapsed;
+                    Trim(now);
+
+                    var longRunning = _parent._loopScheduler.AsLongRunning();
+                    if (longRunning != null)
+                        _loop.Disposable = longRunning.ScheduleLongRunning(Loop);
+                    else
+                        _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec);
+                }
 
-                while (!cancel.IsDisposed)
+                private void LoopRec(Action recurse)
                 {
-                    if (n == 0)
+                    if (_queue.Count > 0)
                     {
-                        base._observer.OnCompleted();
-                        break;
+                        base._observer.OnNext(_queue.Dequeue().Value);
+                        recurse();
                     }
                     else
-                        base._observer.OnNext(_queue.Dequeue().Value);
-
-                    n--;
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
 
-                base.Dispose();
-            }
+                private void Loop(ICancelable cancel)
+                {
+                    var n = _queue.Count;
 
-            private void Trim(TimeSpan now)
-            {
-                while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration)
-                    _queue.Dequeue();
+                    while (!cancel.IsDisposed)
+                    {
+                        if (n == 0)
+                        {
+                            base._observer.OnCompleted();
+                            break;
+                        }
+                        else
+                            base._observer.OnNext(_queue.Dequeue().Value);
+
+                        n--;
+                    }
+
+                    base.Dispose();
+                }
+
+                private void Trim(TimeSpan now)
+                {
+                    while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration)
+                        _queue.Dequeue();
+                }
             }
         }
     }

+ 109 - 103
Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLastBuffer.cs

@@ -7,131 +7,137 @@ using System.Reactive.Concurrency;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class TakeLastBuffer<TSource> : Producer<IList<TSource>>
+    internal static class TakeLastBuffer<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly int _count;
-        private readonly TimeSpan _duration;
-        private readonly IScheduler _scheduler;
-
-        public TakeLastBuffer(IObservable<TSource> source, int count)
+        internal sealed class Count : Producer<IList<TSource>>
         {
-            _source = source;
-            _count = count;
-        }
-
-        public TakeLastBuffer(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
-        {
-            _source = source;
-            _duration = duration;
-            _scheduler = scheduler;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly int _count;
 
-        protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_scheduler == null)
+            public Count(IObservable<TSource> source, int count)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
+                _count = count;
             }
-            else
-            {
-                var sink = new Impl(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
-            }
-        }
 
-        class _ : Sink<IList<TSource>>, IObserver<TSource>
-        {
-            private readonly TakeLastBuffer<TSource> _parent;
-            private Queue<TSource> _queue;
-
-            public _(TakeLastBuffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                _parent = parent;
-                _queue = new Queue<TSource>();
-            }
-
-            public void OnNext(TSource value)
-            {
-                _queue.Enqueue(value);
-                if (_queue.Count > _parent._count)
-                    _queue.Dequeue();
-            }
-
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
+                var sink = new _(_count, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
             }
 
-            public void OnCompleted()
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                var res = new List<TSource>(_queue.Count);
-                while (_queue.Count > 0)
-                    res.Add(_queue.Dequeue());
-
-                base._observer.OnNext(res);
-                base._observer.OnCompleted();
-                base.Dispose();
+                private readonly int _count;
+                private Queue<TSource> _queue;
+
+                public _(int count, IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _count = count;
+                    _queue = new Queue<TSource>();
+                }
+
+                public void OnNext(TSource value)
+                {
+                    _queue.Enqueue(value);
+                    if (_queue.Count > _count)
+                        _queue.Dequeue();
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    var res = new List<TSource>(_queue.Count);
+                    while (_queue.Count > 0)
+                        res.Add(_queue.Dequeue());
+
+                    base._observer.OnNext(res);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class Impl : Sink<IList<TSource>>, IObserver<TSource>
+        internal sealed class Time : Producer<IList<TSource>>
         {
-            private readonly TakeLastBuffer<TSource> _parent;
-            private Queue<System.Reactive.TimeInterval<TSource>> _queue;
-
-            public Impl(TakeLastBuffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
-                _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
-            }
-
-            private IStopwatch _watch;
-
-            public IDisposable Run()
-            {
-                _watch = _parent._scheduler.StartStopwatch();
-
-                return _parent._source.SubscribeSafe(this);
-            }
+            private readonly IObservable<TSource> _source;
+            private readonly TimeSpan _duration;
+            private readonly IScheduler _scheduler;
 
-            public void OnNext(TSource value)
+            public Time(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
             {
-                var now = _watch.Elapsed;
-                _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
-                Trim(now);
+                _source = source;
+                _duration = duration;
+                _scheduler = scheduler;
             }
 
-            public void OnError(Exception error)
+            protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
-
-            public void OnCompleted()
-            {
-                var now = _watch.Elapsed;
-                Trim(now);
-
-                var res = new List<TSource>(_queue.Count);
-                while (_queue.Count > 0)
-                    res.Add(_queue.Dequeue().Value);
-
-                base._observer.OnNext(res);
-                base._observer.OnCompleted();
-                base.Dispose();
+                var sink = new _(_duration, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
             }
 
-            private void Trim(TimeSpan now)
+            private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
             {
-                while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration)
-                    _queue.Dequeue();
+                private readonly TimeSpan _duration;
+                private Queue<System.Reactive.TimeInterval<TSource>> _queue;
+
+                public _(TimeSpan duration, IObserver<IList<TSource>> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _duration = duration;
+                    _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+                }
+
+                private IStopwatch _watch;
+
+                public IDisposable Run(Time parent)
+                {
+                    _watch = parent._scheduler.StartStopwatch();
+
+                    return parent._source.SubscribeSafe(this);
+                }
+
+                public void OnNext(TSource value)
+                {
+                    var now = _watch.Elapsed;
+                    _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
+                    Trim(now);
+                }
+
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
+
+                public void OnCompleted()
+                {
+                    var now = _watch.Elapsed;
+                    Trim(now);
+
+                    var res = new List<TSource>(_queue.Count);
+                    while (_queue.Count > 0)
+                        res.Add(_queue.Dequeue().Value);
+
+                    base._observer.OnNext(res);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
+
+                private void Trim(TimeSpan now)
+                {
+                    while (_queue.Count > 0 && now - _queue.Peek().Interval >= _duration)
+                        _queue.Dequeue();
+                }
             }
         }
     }

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

@@ -20,31 +20,28 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>
+        private sealed class _ : Sink<TSource>
         {
-            private readonly TakeUntil<TSource, TOther> _parent;
-
-            public _(TakeUntil<TSource, TOther> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(TakeUntil<TSource, TOther> parent)
             {
-                var sourceObserver = new T(this);
-                var otherObserver = new O(this, sourceObserver);
+                var sourceObserver = new SourceObserver(this);
+                var otherObserver = new OtherObserver(this, sourceObserver);
 
                 // COMPAT - Order of Subscribe calls per v1.0.10621
-                var otherSubscription = _parent._other.SubscribeSafe(otherObserver);
+                var otherSubscription = parent._other.SubscribeSafe(otherObserver);
                 otherObserver.Disposable = otherSubscription;
 
-                var sourceSubscription = _parent._source.SubscribeSafe(sourceObserver);
+                var sourceSubscription = parent._source.SubscribeSafe(sourceObserver);
 
                 return StableCompositeDisposable.Create(
                     otherSubscription,
@@ -58,7 +55,7 @@ namespace System.Reactive.Linq.ObservableImpl
              * 
              * Notice an approach where the "other" channel performs an Interlocked.Exchange operation on
              * the _parent._observer field to substitute it with a NopObserver<TSource> doesn't work,
-             * because the "other" channel still need to send an OnCompleted message, which could happen
+             * because the "other" channel still needs to send an OnCompleted message, which could happen
              * concurrently with another message when the "source" channel has already read from the
              * _parent._observer field between making the On* call.
              * 
@@ -66,12 +63,12 @@ namespace System.Reactive.Linq.ObservableImpl
              * access to the outgoing observer while dispatching a message. Doing this more fine-grained
              * than using locks turns out to be tricky and doesn't reduce cost.
              */
-            class T : IObserver<TSource>
+            private sealed class SourceObserver : IObserver<TSource>
             {
                 private readonly _ _parent;
                 public volatile bool _open;
 
-                public T(_ parent)
+                public SourceObserver(_ parent)
                 {
                     _parent = parent;
                     _open = false;
@@ -111,13 +108,13 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class O : IObserver<TOther>
+            private sealed class OtherObserver : IObserver<TOther>
             {
                 private readonly _ _parent;
-                private readonly T _sourceObserver;
+                private readonly SourceObserver _sourceObserver;
                 private readonly SingleAssignmentDisposable _subscription;
 
-                public O(_ parent, T sourceObserver)
+                public OtherObserver(_ parent, SourceObserver sourceObserver)
                 {
                     _parent = parent;
                     _sourceObserver = sourceObserver;
@@ -191,29 +188,24 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly TakeUntil<TSource> _parent;
+            private readonly object _gate = new object();
 
-            public _(TakeUntil<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+            public _(IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
-            private object _gate;
-
-            public IDisposable Run()
+            public IDisposable Run(TakeUntil<TSource> parent)
             {
-                _gate = new object();
-
-                var t = _parent._scheduler.Schedule(_parent._endTime, Tick);
-                var d = _parent._source.SubscribeSafe(this);
+                var t = parent._scheduler.Schedule(parent._endTime, Tick);
+                var d = parent._source.SubscribeSafe(this);
                 return StableCompositeDisposable.Create(t, d);
             }
 

+ 106 - 100
Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeWhile.cs

@@ -4,143 +4,149 @@
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class TakeWhile<TSource> : Producer<TSource>
+    internal static class TakeWhile<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly Func<TSource, bool> _predicate;
-        private readonly Func<TSource, int, bool> _predicateI;
-
-        public TakeWhile(IObservable<TSource> source, Func<TSource, bool> predicate)
+        internal sealed class Predicate : Producer<TSource>
         {
-            _source = source;
-            _predicate = predicate;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, bool> _predicate;
 
-        public TakeWhile(IObservable<TSource> source, Func<TSource, int, bool> predicate)
-        {
-            _source = source;
-            _predicateI = predicate;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_predicate != null)
+            public Predicate(IObservable<TSource> source, Func<TSource, bool> predicate)
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return _source.SubscribeSafe(sink);
+                _source = source;
+                _predicate = predicate;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new TakeWhileImpl(this, observer, cancel);
+                var sink = new _(_predicate, observer, cancel);
                 setSink(sink);
                 return _source.SubscribeSafe(sink);
             }
-        }
 
-        class _ : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly TakeWhile<TSource> _parent;
-            private bool _running;
-
-            public _(TakeWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _parent = parent;
-                _running = true;
-            }
+                private readonly Func<TSource, bool> _predicate;
+                private bool _running;
 
-            public void OnNext(TSource value)
-            {
-                if (_running)
+                public _(Func<TSource, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    try
-                    {
-                        _running = _parent._predicate(value);
-                    }
-                    catch (Exception exception)
-                    {
-                        base._observer.OnError(exception);
-                        base.Dispose();
-                        return;
-                    }
+                    _predicate = predicate;
+                    _running = true;
+                }
 
+                public void OnNext(TSource value)
+                {
                     if (_running)
                     {
-                        base._observer.OnNext(value);
-                    }
-                    else
-                    {
-                        base._observer.OnCompleted();
-                        base.Dispose();
+                        try
+                        {
+                            _running = _predicate(value);
+                        }
+                        catch (Exception exception)
+                        {
+                            base._observer.OnError(exception);
+                            base.Dispose();
+                            return;
+                        }
+
+                        if (_running)
+                        {
+                            base._observer.OnNext(value);
+                        }
+                        else
+                        {
+                            base._observer.OnCompleted();
+                            base.Dispose();
+                        }
                     }
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
 
-            public void OnCompleted()
-            {
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class TakeWhileImpl : Sink<TSource>, IObserver<TSource>
+        internal sealed class PredicateIndexed : Producer<TSource>
         {
-            private readonly TakeWhile<TSource> _parent;
-            private bool _running;
-            private int _index;
+            private readonly IObservable<TSource> _source;
+            private readonly Func<TSource, int, bool> _predicate;
 
-            public TakeWhileImpl(TakeWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public PredicateIndexed(IObservable<TSource> source, Func<TSource, int, bool> predicate)
             {
-                _parent = parent;
-                _running = true;
-                _index = 0;
+                _source = source;
+                _predicate = predicate;
             }
 
-            public void OnNext(TSource value)
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                if (_running)
+                var sink = new _(_predicate, observer, cancel);
+                setSink(sink);
+                return _source.SubscribeSafe(sink);
+            }
+
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
+            {
+                private readonly Func<TSource, int, bool> _predicate;
+                private bool _running;
+                private int _index;
+
+                public _(Func<TSource, int, bool> predicate, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    try
-                    {
-                        _running = _parent._predicateI(value, checked(_index++));
-                    }
-                    catch (Exception exception)
-                    {
-                        base._observer.OnError(exception);
-                        base.Dispose();
-                        return;
-                    }
+                    _predicate = predicate;
+                    _running = true;
+                    _index = 0;
+                }
 
+                public void OnNext(TSource value)
+                {
                     if (_running)
                     {
-                        base._observer.OnNext(value);
-                    }
-                    else
-                    {
-                        base._observer.OnCompleted();
-                        base.Dispose();
+                        try
+                        {
+                            _running = _predicate(value, checked(_index++));
+                        }
+                        catch (Exception exception)
+                        {
+                            base._observer.OnError(exception);
+                            base.Dispose();
+                            return;
+                        }
+
+                        if (_running)
+                        {
+                            base._observer.OnNext(value);
+                        }
+                        else
+                        {
+                            base._observer.OnCompleted();
+                            base.Dispose();
+                        }
                     }
                 }
-            }
 
-            public void OnError(Exception error)
-            {
-                base._observer.OnError(error);
-                base.Dispose();
-            }
+                public void OnError(Exception error)
+                {
+                    base._observer.OnError(error);
+                    base.Dispose();
+                }
 
-            public void OnCompleted()
-            {
-                base._observer.OnCompleted();
-                base.Dispose();
+                public void OnCompleted()
+                {
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
     }

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

@@ -24,17 +24,19 @@ namespace System.Reactive.Linq.ObservableImpl
         {
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_source);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Throttle<TSource> _parent;
+            private readonly TimeSpan _dueTime;
+            private readonly IScheduler _scheduler;
 
             public _(Throttle<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _dueTime = parent._dueTime;
+                _scheduler = parent._scheduler;
             }
 
             private object _gate;
@@ -43,7 +45,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private SerialDisposable _cancelable;
             private ulong _id;
 
-            public IDisposable Run()
+            public IDisposable Run(IObservable<TSource> source)
             {
                 _gate = new object();
                 _value = default(TSource);
@@ -51,7 +53,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 _cancelable = new SerialDisposable();
                 _id = 0UL;
 
-                var subscription = _parent._source.SubscribeSafe(this);
+                var subscription = source.SubscribeSafe(this);
 
                 return StableCompositeDisposable.Create(subscription, _cancelable);
             }
@@ -68,7 +70,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
                 var d = new SingleAssignmentDisposable();
                 _cancelable.Disposable = d;
-                d.Disposable = _parent._scheduler.Schedule(currentid, _parent._dueTime, Propagate);
+                d.Disposable = _scheduler.Schedule(currentid, _dueTime, Propagate);
             }
 
             private IDisposable Propagate(IScheduler self, ulong currentid)
@@ -94,7 +96,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                     _hasValue = false;
                     _id = unchecked(_id + 1);
-                }                        
+                }
             }
 
             public void OnCompleted()
@@ -105,7 +107,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 {
                     if (_hasValue)
                         base._observer.OnNext(_value);
-                    
+
                     base._observer.OnCompleted();
                     base.Dispose();
 
@@ -131,17 +133,17 @@ namespace System.Reactive.Linq.ObservableImpl
         {
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Throttle<TSource, TThrottle> _parent;
+            private readonly Func<TSource, IObservable<TThrottle>> _throttleSelector;
 
             public _(Throttle<TSource, TThrottle> parent, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _throttleSelector = parent._throttleSelector;
             }
 
             private object _gate;
@@ -150,7 +152,7 @@ namespace System.Reactive.Linq.ObservableImpl
             private SerialDisposable _cancelable;
             private ulong _id;
 
-            public IDisposable Run()
+            public IDisposable Run(Throttle<TSource, TThrottle> parent)
             {
                 _gate = new object();
                 _value = default(TSource);
@@ -158,7 +160,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 _cancelable = new SerialDisposable();
                 _id = 0UL;
 
-                var subscription = _parent._source.SubscribeSafe(this);
+                var subscription = parent._source.SubscribeSafe(this);
 
                 return StableCompositeDisposable.Create(subscription, _cancelable);
             }
@@ -168,7 +170,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 var throttle = default(IObservable<TThrottle>);
                 try
                 {
-                    throttle = _parent._throttleSelector(value);
+                    throttle = _throttleSelector(value);
                 }
                 catch (Exception error)
                 {
@@ -192,7 +194,7 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 var d = new SingleAssignmentDisposable();
                 _cancelable.Disposable = d;
-                d.Disposable = throttle.SubscribeSafe(new Delta(this, value, currentid, d));
+                d.Disposable = throttle.SubscribeSafe(new ThrottleObserver(this, value, currentid, d));
             }
 
             public void OnError(Exception error)
@@ -226,14 +228,14 @@ namespace System.Reactive.Linq.ObservableImpl
                 }
             }
 
-            class Delta : IObserver<TThrottle>
+            private sealed class ThrottleObserver : IObserver<TThrottle>
             {
                 private readonly _ _parent;
                 private readonly TSource _value;
                 private readonly ulong _currentid;
                 private readonly IDisposable _self;
 
-                public Delta(_ parent, TSource value, ulong currentid, IDisposable self)
+                public ThrottleObserver(_ parent, TSource value, ulong currentid, IDisposable self)
                 {
                     _parent = parent;
                     _value = value;

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

@@ -19,29 +19,29 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_exception, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(_scheduler);
         }
 
-        class _ : Sink<TResult>
+        private sealed class _ : Sink<TResult>
         {
-            private readonly Throw<TResult> _parent;
+            private readonly Exception _exception;
 
-            public _(Throw<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+            public _(Exception exception, IObserver<TResult> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _exception = exception;
             }
 
-            public IDisposable Run()
+            public IDisposable Run(IScheduler scheduler)
             {
-                return _parent._scheduler.Schedule(Invoke);
+                return scheduler.Schedule(Invoke);
             }
 
             private void Invoke()
             {
-                base._observer.OnError(_parent._exception);
+                base._observer.OnError(_exception);
                 base.Dispose();
             }
         }

+ 7 - 10
Rx.NET/Source/src/System.Reactive/Linq/Observable/TimeInterval.cs

@@ -19,30 +19,27 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<System.Reactive.TimeInterval<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<System.Reactive.TimeInterval<TSource>>, IObserver<TSource>
+        private sealed class _ : Sink<System.Reactive.TimeInterval<TSource>>, IObserver<TSource>
         {
-            private readonly TimeInterval<TSource> _parent;
-
-            public _(TimeInterval<TSource> parent, IObserver<System.Reactive.TimeInterval<TSource>> observer, IDisposable cancel)
+            public _(IObserver<System.Reactive.TimeInterval<TSource>> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
             }
 
             private IStopwatch _watch;
             private TimeSpan _last;
 
-            public IDisposable Run()
+            public IDisposable Run(TimeInterval<TSource> parent)
             {
-                _watch = _parent._scheduler.StartStopwatch();
+                _watch = parent._scheduler.StartStopwatch();
                 _last = TimeSpan.Zero;
 
-                return _parent._source.Subscribe(this);
+                return parent._source.Subscribe(this);
             }
 
             public void OnNext(TSource value)

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

@@ -7,250 +7,258 @@ using System.Reactive.Disposables;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Timeout<TSource> : Producer<TSource>
+    internal static class Timeout<TSource>
     {
-        private readonly IObservable<TSource> _source;
-        private readonly TimeSpan? _dueTimeR;
-        private readonly DateTimeOffset? _dueTimeA;
-        private readonly IObservable<TSource> _other;
-        private readonly IScheduler _scheduler;
-
-        public Timeout(IObservable<TSource> source, TimeSpan dueTime, IObservable<TSource> other, IScheduler scheduler)
+        internal sealed class Relative : Producer<TSource>
         {
-            _source = source;
-            _dueTimeR = dueTime;
-            _other = other;
-            _scheduler = scheduler;
-        }
+            private readonly IObservable<TSource> _source;
+            private readonly TimeSpan _dueTime;
+            private readonly IObservable<TSource> _other;
+            private readonly IScheduler _scheduler;
 
-        public Timeout(IObservable<TSource> source, DateTimeOffset dueTime, IObservable<TSource> other, IScheduler scheduler)
-        {
-            _source = source;
-            _dueTimeA = dueTime;
-            _other = other;
-            _scheduler = scheduler;
-        }
-
-        protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_dueTimeA.HasValue)
+            public Relative(IObservable<TSource> source, TimeSpan dueTime, IObservable<TSource> other, IScheduler scheduler)
             {
-                var sink = new TimeA(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _source = source;
+                _dueTime = dueTime;
+                _other = other;
+                _scheduler = scheduler;
             }
-            else
+
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
             {
-                var sink = new TimeR(this, observer, cancel);
+                var sink = new _(this, observer, cancel);
                 setSink(sink);
-                return sink.Run();
+                return sink.Run(_source);
             }
-        }
-
-        class TimeA : Sink<TSource>, IObserver<TSource>
-        {
-            private readonly Timeout<TSource> _parent;
 
-            public TimeA(Timeout<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _parent = parent;
-            }
+                private readonly TimeSpan _dueTime;
+                private readonly IObservable<TSource> _other;
+                private readonly IScheduler _scheduler;
 
-            private SerialDisposable _subscription;
-            private object _gate;
-            private bool _switched;
+                private readonly object _gate = new object();
+                private SerialDisposable _subscription = new SerialDisposable();
+                private SerialDisposable _timer = new SerialDisposable();
 
-            public IDisposable Run()
-            {
-                _subscription = new SerialDisposable();
-                var original = new SingleAssignmentDisposable();
+                public _(Relative parent, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _dueTime = parent._dueTime;
+                    _other = parent._other;
+                    _scheduler = parent._scheduler;
+                }
 
-                _subscription.Disposable = original;
+                private ulong _id;
+                private bool _switched;
 
-                _gate = new object();
-                _switched = false;
+                public IDisposable Run(IObservable<TSource> source)
+                {
+                    var original = new SingleAssignmentDisposable();
 
-                var timer = _parent._scheduler.Schedule(_parent._dueTimeA.Value, Timeout);
+                    _subscription.Disposable = original;
 
-                original.Disposable = _parent._source.SubscribeSafe(this);
+                    _id = 0UL;
+                    _switched = false;
 
-                return StableCompositeDisposable.Create(_subscription, timer);
-            }
+                    CreateTimer();
 
-            private void Timeout()
-            {
-                var timerWins = false;
+                    original.Disposable = source.SubscribeSafe(this);
 
-                lock (_gate)
-                {
-                    timerWins = !_switched;
-                    _switched = true;
+                    return StableCompositeDisposable.Create(_subscription, _timer);
                 }
 
-                if (timerWins)
-                    _subscription.Disposable = _parent._other.SubscribeSafe(this.GetForwarder());
-            }
-
-            public void OnNext(TSource value)
-            {
-                lock (_gate)
+                private void CreateTimer()
                 {
-                    if (!_switched)
-                        base._observer.OnNext(value);
+                    _timer.Disposable = _scheduler.Schedule(_id, _dueTime, Timeout);
                 }
-            }
-
-            public void OnError(Exception error)
-            {
-                var onErrorWins = false;
 
-                lock (_gate)
+                private IDisposable Timeout(IScheduler _, ulong myid)
                 {
-                    onErrorWins = !_switched;
-                    _switched = true;
+                    var timerWins = false;
+
+                    lock (_gate)
+                    {
+                        _switched = (_id == myid);
+                        timerWins = _switched;
+                    }
+
+                    if (timerWins)
+                        _subscription.Disposable = _other.SubscribeSafe(this.GetForwarder());
+
+                    return Disposable.Empty;
                 }
 
-                if (onErrorWins)
+                public void OnNext(TSource value)
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
-                }
-            }
+                    var onNextWins = false;
 
-            public void OnCompleted()
-            {
-                var onCompletedWins = false;
+                    lock (_gate)
+                    {
+                        onNextWins = !_switched;
+                        if (onNextWins)
+                        {
+                            _id = unchecked(_id + 1);
+                        }
+                    }
 
-                lock (_gate)
+                    if (onNextWins)
+                    {
+                        base._observer.OnNext(value);
+                        CreateTimer();
+                    }
+                }
+
+                public void OnError(Exception error)
                 {
-                    onCompletedWins = !_switched;
-                    _switched = true;
+                    var onErrorWins = false;
+
+                    lock (_gate)
+                    {
+                        onErrorWins = !_switched;
+                        if (onErrorWins)
+                        {
+                            _id = unchecked(_id + 1);
+                        }
+                    }
+
+                    if (onErrorWins)
+                    {
+                        base._observer.OnError(error);
+                        base.Dispose();
+                    }
                 }
 
-                if (onCompletedWins)
+                public void OnCompleted()
                 {
-                    base._observer.OnCompleted();
-                    base.Dispose();
+                    var onCompletedWins = false;
+
+                    lock (_gate)
+                    {
+                        onCompletedWins = !_switched;
+                        if (onCompletedWins)
+                        {
+                            _id = unchecked(_id + 1);
+                        }
+                    }
+
+                    if (onCompletedWins)
+                    {
+                        base._observer.OnCompleted();
+                        base.Dispose();
+                    }
                 }
             }
         }
 
-        class TimeR : Sink<TSource>, IObserver<TSource>
+        internal sealed class Absolute : Producer<TSource>
         {
-            private readonly Timeout<TSource> _parent;
+            private readonly IObservable<TSource> _source;
+            private readonly DateTimeOffset _dueTime;
+            private readonly IObservable<TSource> _other;
+            private readonly IScheduler _scheduler;
 
-            public TimeR(Timeout<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Absolute(IObservable<TSource> source, DateTimeOffset dueTime, IObservable<TSource> other, IScheduler scheduler)
             {
-                _parent = parent;
+                _source = source;
+                _dueTime = dueTime;
+                _other = other;
+                _scheduler = scheduler;
             }
 
-            private SerialDisposable _subscription;
-            private SerialDisposable _timer;
-
-            private object _gate;
-            private ulong _id;
-            private bool _switched;
+            protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+            {
+                var sink = new _(_other, observer, cancel);
+                setSink(sink);
+                return sink.Run(this);
+            }
 
-            public IDisposable Run()
+            private sealed class _ : Sink<TSource>, IObserver<TSource>
             {
-                _subscription = new SerialDisposable();
-                _timer = new SerialDisposable();
-                var original = new SingleAssignmentDisposable();
+                private readonly IObservable<TSource> _other;
 
-                _subscription.Disposable = original;
+                private readonly object _gate = new object();
+                private readonly SerialDisposable _subscription = new SerialDisposable();
 
-                _gate = new object();
-                _id = 0UL;
-                _switched = false;
+                public _(IObservable<TSource> other, IObserver<TSource> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                    _other = other;
+                }
 
-                CreateTimer();
+                private bool _switched;
 
-                original.Disposable = _parent._source.SubscribeSafe(this);
+                public IDisposable Run(Absolute parent)
+                {
+                    var original = new SingleAssignmentDisposable();
 
-                return StableCompositeDisposable.Create(_subscription, _timer);
-            }
+                    _subscription.Disposable = original;
 
-            private void CreateTimer()
-            {
-                _timer.Disposable = _parent._scheduler.Schedule(_id, _parent._dueTimeR.Value, Timeout);
-            }
+                    _switched = false;
 
-            private IDisposable Timeout(IScheduler _, ulong myid)
-            {
-                var timerWins = false;
+                    var timer = parent._scheduler.Schedule(parent._dueTime, Timeout);
 
-                lock (_gate)
-                {
-                    _switched = (_id == myid);
-                    timerWins = _switched;
+                    original.Disposable = parent._source.SubscribeSafe(this);
+
+                    return StableCompositeDisposable.Create(_subscription, timer);
                 }
 
-                if (timerWins)
-                    _subscription.Disposable = _parent._other.SubscribeSafe(this.GetForwarder());
+                private void Timeout()
+                {
+                    var timerWins = false;
 
-                return Disposable.Empty;
-            }
+                    lock (_gate)
+                    {
+                        timerWins = !_switched;
+                        _switched = true;
+                    }
 
-            public void OnNext(TSource value)
-            {
-                var onNextWins = false;
+                    if (timerWins)
+                        _subscription.Disposable = _other.SubscribeSafe(this.GetForwarder());
+                }
 
-                lock (_gate)
+                public void OnNext(TSource value)
                 {
-                    onNextWins = !_switched;
-                    if (onNextWins)
+                    lock (_gate)
                     {
-                        _id = unchecked(_id + 1);
+                        if (!_switched)
+                            base._observer.OnNext(value);
                     }
                 }
 
-                if (onNextWins)
+                public void OnError(Exception error)
                 {
-                    base._observer.OnNext(value);
-                    CreateTimer();
-                }
-            }
+                    var onErrorWins = false;
 
-            public void OnError(Exception error)
-            {
-                var onErrorWins = false;
+                    lock (_gate)
+                    {
+                        onErrorWins = !_switched;
+                        _switched = true;
+                    }
 
-                lock (_gate)
-                {
-                    onErrorWins = !_switched;
                     if (onErrorWins)
                     {
-                        _id = unchecked(_id + 1);
+                        base._observer.OnError(error);
+                        base.Dispose();
                     }
                 }
 
-                if (onErrorWins)
+                public void OnCompleted()
                 {
-                    base._observer.OnError(error);
-                    base.Dispose();
-                }
-            }
+                    var onCompletedWins = false;
 
-            public void OnCompleted()
-            {
-                var onCompletedWins = false;
+                    lock (_gate)
+                    {
+                        onCompletedWins = !_switched;
+                        _switched = true;
+                    }
 
-                lock (_gate)
-                {
-                    onCompletedWins = !_switched;
                     if (onCompletedWins)
                     {
-                        _id = unchecked(_id + 1);
+                        base._observer.OnCompleted();
+                        base.Dispose();
                     }
                 }
-
-                if (onCompletedWins)
-                {
-                    base._observer.OnCompleted();
-                    base.Dispose();
-                }
             }
         }
     }
@@ -274,40 +282,40 @@ namespace System.Reactive.Linq.ObservableImpl
         {
             var sink = new _(this, observer, cancel);
             setSink(sink);
-            return sink.Run();
+            return sink.Run(this);
         }
 
-        class _ : Sink<TSource>, IObserver<TSource>
+        private sealed class _ : Sink<TSource>, IObserver<TSource>
         {
-            private readonly Timeout<TSource, TTimeout> _parent;
+            private readonly Func<TSource, IObservable<TTimeout>> _timeoutSelector;
+            private readonly IObservable<TSource> _other;
+
+            private readonly object _gate = new object();
+            private readonly SerialDisposable _subscription = new SerialDisposable();
+            private readonly SerialDisposable _timer = new SerialDisposable();
 
             public _(Timeout<TSource, TTimeout> parent, IObserver<TSource> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _timeoutSelector = parent._timeoutSelector;
+                _other = parent._other;
             }
 
-            private SerialDisposable _subscription;
-            private SerialDisposable _timer;
-            private object _gate;
             private ulong _id;
             private bool _switched;
 
-            public IDisposable Run()
+            public IDisposable Run(Timeout<TSource, TTimeout> parent)
             {
-                _subscription = new SerialDisposable();
-                _timer = new SerialDisposable();
                 var original = new SingleAssignmentDisposable();
 
                 _subscription.Disposable = original;
 
-                _gate = new object();
                 _id = 0UL;
                 _switched = false;
 
-                SetTimer(_parent._firstTimeout);
+                SetTimer(parent._firstTimeout);
 
-                original.Disposable = _parent._source.SubscribeSafe(this);
+                original.Disposable = parent._source.SubscribeSafe(this);
 
                 return StableCompositeDisposable.Create(_subscription, _timer);
             }
@@ -321,7 +329,7 @@ namespace System.Reactive.Linq.ObservableImpl
                     var timeout = default(IObservable<TTimeout>);
                     try
                     {
-                        timeout = _parent._timeoutSelector(value);
+                        timeout = _timeoutSelector(value);
                     }
                     catch (Exception error)
                     {
@@ -358,16 +366,16 @@ namespace System.Reactive.Linq.ObservableImpl
 
                 var d = new SingleAssignmentDisposable();
                 _timer.Disposable = d;
-                d.Disposable = timeout.SubscribeSafe(new TimeoutImpl(this, myid, d));
+                d.Disposable = timeout.SubscribeSafe(new TimeoutObserver(this, myid, d));
             }
 
-            class TimeoutImpl : IObserver<TTimeout>
+            private sealed class TimeoutObserver : IObserver<TTimeout>
             {
                 private readonly _ _parent;
                 private readonly ulong _id;
                 private readonly IDisposable _self;
 
-                public TimeoutImpl(_ parent, ulong id, IDisposable self)
+                public TimeoutObserver(_ parent, ulong id, IDisposable self)
                 {
                     _parent = parent;
                     _id = id;
@@ -377,7 +385,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 public void OnNext(TTimeout value)
                 {
                     if (TimerWins())
-                        _parent._subscription.Disposable = _parent._parent._other.SubscribeSafe(_parent.GetForwarder());
+                        _parent._subscription.Disposable = _parent._other.SubscribeSafe(_parent.GetForwarder());
 
                     _self.Dispose();
                 }
@@ -394,7 +402,7 @@ namespace System.Reactive.Linq.ObservableImpl
                 public void OnCompleted()
                 {
                     if (TimerWins())
-                        _parent._subscription.Disposable = _parent._parent._other.SubscribeSafe(_parent.GetForwarder());
+                        _parent._subscription.Disposable = _parent._other.SubscribeSafe(_parent.GetForwarder());
                 }
 
                 private bool TimerWins()

+ 231 - 184
Rx.NET/Source/src/System.Reactive/Linq/Observable/Timer.cs

@@ -8,253 +8,300 @@ using System.Threading;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
-    internal sealed class Timer : Producer<long>
+    internal static class Timer
     {
-        private readonly DateTimeOffset? _dueTimeA;
-        private readonly TimeSpan? _dueTimeR;
-        private readonly TimeSpan? _period;
-        private readonly IScheduler _scheduler;
-
-        public Timer(DateTimeOffset dueTime, TimeSpan? period, IScheduler scheduler)
-        {
-            _dueTimeA = dueTime;
-            _period = period;
-            _scheduler = scheduler;
-        }
-
-        public Timer(TimeSpan dueTime, TimeSpan? period, IScheduler scheduler)
+        internal abstract class Single : Producer<long>
         {
-            _dueTimeR = dueTime;
-            _period = period;
-            _scheduler = scheduler;
-        }
+            private readonly IScheduler _scheduler;
 
-        protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
-        {
-            if (_period.HasValue)
+            public Single(IScheduler scheduler)
             {
-                var sink = new TimerImpl(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
+                _scheduler = scheduler;
             }
-            else
+
+            internal sealed class Relative : Single
             {
-                var sink = new _(this, observer, cancel);
-                setSink(sink);
-                return sink.Run();
-            }
-        }
+                private readonly TimeSpan _dueTime;
 
-        class _ : Sink<long>
-        {
-            private readonly Timer _parent;
+                public Relative(TimeSpan dueTime, IScheduler scheduler)
+                    : base(scheduler)
+                {
+                    _dueTime = dueTime;
+                }
 
-            public _(Timer parent, IObserver<long> observer, IDisposable cancel)
-                : base(observer, cancel)
-            {
-                _parent = parent;
+                protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+                {
+                    var sink = new _(observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this, _dueTime);
+                }
             }
 
-            public IDisposable Run()
+            internal sealed class Absolute : Single
             {
-                if (_parent._dueTimeA.HasValue)
+                private readonly DateTimeOffset _dueTime;
+
+                public Absolute(DateTimeOffset dueTime, IScheduler scheduler)
+                    : base(scheduler)
                 {
-                    return _parent._scheduler.Schedule(_parent._dueTimeA.Value, Invoke);
+                    _dueTime = dueTime;
                 }
-                else
+
+                protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
                 {
-                    return _parent._scheduler.Schedule(_parent._dueTimeR.Value, Invoke);
+                    var sink = new _(observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this, _dueTime);
                 }
             }
 
-            private void Invoke()
+            private sealed class _ : Sink<long>
             {
-                base._observer.OnNext(0);
-                base._observer.OnCompleted();
-                base.Dispose();
+                public _(IObserver<long> observer, IDisposable cancel)
+                    : base(observer, cancel)
+                {
+                }
+
+                public IDisposable Run(Single parent, DateTimeOffset dueTime)
+                {
+                    return parent._scheduler.Schedule(dueTime, Invoke);
+                }
+
+                public IDisposable Run(Single parent, TimeSpan dueTime)
+                {
+                    return parent._scheduler.Schedule(dueTime, Invoke);
+                }
+
+                private void Invoke()
+                {
+                    base._observer.OnNext(0);
+                    base._observer.OnCompleted();
+                    base.Dispose();
+                }
             }
         }
 
-        class TimerImpl : Sink<long>
+        internal abstract class Periodic : Producer<long>
         {
-            private readonly Timer _parent;
             private readonly TimeSpan _period;
+            private readonly IScheduler _scheduler;
 
-            public TimerImpl(Timer parent, IObserver<long> observer, IDisposable cancel)
-                : base(observer, cancel)
+            public Periodic(TimeSpan period, IScheduler scheduler)
             {
-                _parent = parent;
-                _period = _parent._period.Value;
+                _period = period;
+                _scheduler = scheduler;
             }
 
-            public IDisposable Run()
+            internal sealed class Relative : Periodic
             {
-                if (_parent._dueTimeA.HasValue)
+                private readonly TimeSpan _dueTime;
+
+                public Relative(TimeSpan dueTime, TimeSpan period, IScheduler scheduler)
+                    : base(period, scheduler)
                 {
-                    var dueTime = _parent._dueTimeA.Value;
-                    return _parent._scheduler.Schedule(default(object), dueTime, InvokeStart);
+                    _dueTime = dueTime;
                 }
-                else
-                {
-                    var dueTime = _parent._dueTimeR.Value;
 
-                    //
-                    // Optimize for the case of Observable.Interval.
-                    //
-                    if (dueTime == _period)
-                    {
-                        return _parent._scheduler.SchedulePeriodic(0L, _period, (Func<long, long>)Tick);
-                    }
-
-                    return _parent._scheduler.Schedule(default(object), dueTime, InvokeStart);
+                protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+                {
+                    var sink = new _(_period, observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this, _dueTime);
                 }
             }
 
-            //
-            // BREAKING CHANGE v2 > v1.x - No more correction for time drift based on absolute time. This
-            //                             didn't work for large period values anyway; the fractional
-            //                             error exceeded corrections. Also complicated dealing with system
-            //                             clock change conditions and caused numerous bugs.
-            //
-            // - For more precise scheduling, use a custom scheduler that measures TimeSpan values in a
-            //   better way, e.g. spinning to make up for the last part of the period. Whether or not the
-            //   values of the TimeSpan period match NT time or wall clock time is up to the scheduler.
-            //
-            // - For more accurate scheduling wrt the system clock, use Generate with DateTimeOffset time
-            //   selectors. When the system clock changes, intervals will not be the same as diffs between
-            //   consecutive absolute time values. The precision will be low (1s range by default).
-            //
-            private long Tick(long count)
+            internal sealed class Absolute : Periodic
             {
-                base._observer.OnNext(count);
-                return unchecked(count + 1);
-            }
-
-            private int _pendingTickCount;
-            private IDisposable _periodic;
+                private readonly DateTimeOffset _dueTime;
 
-            private IDisposable InvokeStart(IScheduler self, object state)
-            {
-                //
-                // Notice the first call to OnNext will introduce skew if it takes significantly long when
-                // using the following naive implementation:
-                //
-                //    Code:  base._observer.OnNext(0L);
-                //           return self.SchedulePeriodicEmulated(1L, _period, (Func<long, long>)Tick);
-                //
-                // What we're saying here is that Observable.Timer(dueTime, period) is pretty much the same
-                // as writing Observable.Timer(dueTime).Concat(Observable.Interval(period)).
-                //
-                //    Expected:  dueTime
-                //                  |
-                //                  0--period--1--period--2--period--3--period--4--...
-                //                  |
-                //                  +-OnNext(0L)-|
-                //    
-                //    Actual:    dueTime
-                //                  |
-                //                  0------------#--period--1--period--2--period--3--period--4--...
-                //                  |
-                //                  +-OnNext(0L)-|
-                //
-                // Different solutions for this behavior have different problems:
-                //
-                // 1. Scheduling the periodic job first and using an AsyncLock to serialize the OnNext calls
-                //    has the drawback that InvokeStart may never return. This happens when every callback
-                //    doesn't meet the period's deadline, hence the periodic job keeps queueing stuff up. In
-                //    this case, InvokeStart stays the owner of the AsyncLock and the call to Wait will never
-                //    return, thus not allowing any interleaving of work on this scheduler's logical thread.
-                //
-                // 2. Scheduling the periodic job first and using a (blocking) synchronization primitive to
-                //    signal completion of the OnNext(0L) call to the Tick call requires quite a bit of state
-                //    and careful handling of the case when OnNext(0L) throws. What's worse is the blocking
-                //    behavior inside Tick.
-                //
-                // In order to avoid blocking behavior, we need a scheme much like SchedulePeriodic emulation
-                // where work to dispatch OnNext(n + 1) is delegated to a catch up loop in case OnNext(n) was
-                // still running. Because SchedulePeriodic emulation exhibits such behavior in all cases, we
-                // only need to deal with the overlap of OnNext(0L) with future periodic OnNext(n) dispatch
-                // jobs. In the worst case where every callback takes longer than the deadline implied by the
-                // period, the periodic job will just queue up work that's dispatched by the tail-recursive
-                // catch up loop. In the best case, all work will be dispatched on the periodic scheduler.
-                //
+                public Absolute(DateTimeOffset dueTime, TimeSpan period, IScheduler scheduler)
+                    : base(period, scheduler)
+                {
+                    _dueTime = dueTime;
+                }
 
-                //
-                // We start with one tick pending because we're about to start doing OnNext(0L).
-                //
-                _pendingTickCount = 1;
+                protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+                {
+                    var sink = new _(_period, observer, cancel);
+                    setSink(sink);
+                    return sink.Run(this, _dueTime);
+                }
+            }
 
-                var d = new SingleAssignmentDisposable();
-                _periodic = d;
-                d.Disposable = self.SchedulePeriodic(1L, _period, (Func<long, long>)Tock);
+            private sealed class _ : Sink<long>
+            {
+                private readonly TimeSpan _period;
 
-                try
+                public _(TimeSpan period, IObserver<long> observer, IDisposable cancel)
+                    : base(observer, cancel)
                 {
-                    base._observer.OnNext(0L);
+                    _period = period;
                 }
-                catch (Exception e)
+
+                public IDisposable Run(Periodic parent, DateTimeOffset dueTime)
                 {
-                    d.Dispose();
-                    e.Throw();
+                    return parent._scheduler.Schedule(default(object), dueTime, InvokeStart);
                 }
 
-                //
-                // If the periodic scheduling job already ran before we finished dispatching the OnNext(0L)
-                // call, we'll find pendingTickCount to be > 1. In this case, we need to catch up by dispatching
-                // subsequent calls to OnNext as fast as possible, but without running a loop in order to ensure
-                // fair play with the scheduler. So, we run a tail-recursive loop in CatchUp instead.
-                //
-                if (Interlocked.Decrement(ref _pendingTickCount) > 0)
+                public IDisposable Run(Periodic parent, TimeSpan dueTime)
                 {
-                    var c = new SingleAssignmentDisposable();
-                    c.Disposable = self.Schedule(1L, CatchUp);
+                    //
+                    // Optimize for the case of Observable.Interval.
+                    //
+                    if (dueTime == _period)
+                    {
+                        return parent._scheduler.SchedulePeriodic(0L, _period, (Func<long, long>)Tick);
+                    }
 
-                    return StableCompositeDisposable.Create(d, c);
+                    return parent._scheduler.Schedule(default(object), dueTime, InvokeStart);
                 }
 
-                return d;
-            }
-
-            private long Tock(long count)
-            {
                 //
-                // Notice the handler for (emulated) periodic scheduling is non-reentrant.
+                // BREAKING CHANGE v2 > v1.x - No more correction for time drift based on absolute time. This
+                //                             didn't work for large period values anyway; the fractional
+                //                             error exceeded corrections. Also complicated dealing with system
+                //                             clock change conditions and caused numerous bugs.
                 //
-                // When there's no overlap with the OnNext(0L) call, the following code will cycle through
-                // pendingTickCount 0 -> 1 -> 0 for the remainder of the timer's execution.
+                // - For more precise scheduling, use a custom scheduler that measures TimeSpan values in a
+                //   better way, e.g. spinning to make up for the last part of the period. Whether or not the
+                //   values of the TimeSpan period match NT time or wall clock time is up to the scheduler.
                 //
-                // If there's overlap with the OnNext(0L) call, pendingTickCount will increase to record
-                // the number of catch up OnNext calls required, which will be dispatched by the recursive
-                // scheduling loop in CatchUp (which quits when it reaches 0 pending ticks).
+                // - For more accurate scheduling wrt the system clock, use Generate with DateTimeOffset time
+                //   selectors. When the system clock changes, intervals will not be the same as diffs between
+                //   consecutive absolute time values. The precision will be low (1s range by default).
                 //
-                if (Interlocked.Increment(ref _pendingTickCount) == 1)
+                private long Tick(long count)
                 {
                     base._observer.OnNext(count);
-                    Interlocked.Decrement(ref _pendingTickCount);
+                    return unchecked(count + 1);
                 }
 
-                return unchecked(count + 1);
-            }
+                private int _pendingTickCount;
+                private IDisposable _periodic;
 
-            private void CatchUp(long count, Action<long> recurse)
-            {
-                try
+                private IDisposable InvokeStart(IScheduler self, object state)
                 {
-                    base._observer.OnNext(count);
+                    //
+                    // Notice the first call to OnNext will introduce skew if it takes significantly long when
+                    // using the following naive implementation:
+                    //
+                    //    Code:  base._observer.OnNext(0L);
+                    //           return self.SchedulePeriodicEmulated(1L, _period, (Func<long, long>)Tick);
+                    //
+                    // What we're saying here is that Observable.Timer(dueTime, period) is pretty much the same
+                    // as writing Observable.Timer(dueTime).Concat(Observable.Interval(period)).
+                    //
+                    //    Expected:  dueTime
+                    //                  |
+                    //                  0--period--1--period--2--period--3--period--4--...
+                    //                  |
+                    //                  +-OnNext(0L)-|
+                    //    
+                    //    Actual:    dueTime
+                    //                  |
+                    //                  0------------#--period--1--period--2--period--3--period--4--...
+                    //                  |
+                    //                  +-OnNext(0L)-|
+                    //
+                    // Different solutions for this behavior have different problems:
+                    //
+                    // 1. Scheduling the periodic job first and using an AsyncLock to serialize the OnNext calls
+                    //    has the drawback that InvokeStart may never return. This happens when every callback
+                    //    doesn't meet the period's deadline, hence the periodic job keeps queueing stuff up. In
+                    //    this case, InvokeStart stays the owner of the AsyncLock and the call to Wait will never
+                    //    return, thus not allowing any interleaving of work on this scheduler's logical thread.
+                    //
+                    // 2. Scheduling the periodic job first and using a (blocking) synchronization primitive to
+                    //    signal completion of the OnNext(0L) call to the Tick call requires quite a bit of state
+                    //    and careful handling of the case when OnNext(0L) throws. What's worse is the blocking
+                    //    behavior inside Tick.
+                    //
+                    // In order to avoid blocking behavior, we need a scheme much like SchedulePeriodic emulation
+                    // where work to dispatch OnNext(n + 1) is delegated to a catch up loop in case OnNext(n) was
+                    // still running. Because SchedulePeriodic emulation exhibits such behavior in all cases, we
+                    // only need to deal with the overlap of OnNext(0L) with future periodic OnNext(n) dispatch
+                    // jobs. In the worst case where every callback takes longer than the deadline implied by the
+                    // period, the periodic job will just queue up work that's dispatched by the tail-recursive
+                    // catch up loop. In the best case, all work will be dispatched on the periodic scheduler.
+                    //
+
+                    //
+                    // We start with one tick pending because we're about to start doing OnNext(0L).
+                    //
+                    _pendingTickCount = 1;
+
+                    var d = new SingleAssignmentDisposable();
+                    _periodic = d;
+                    d.Disposable = self.SchedulePeriodic(1L, _period, (Func<long, long>)Tock);
+
+                    try
+                    {
+                        base._observer.OnNext(0L);
+                    }
+                    catch (Exception e)
+                    {
+                        d.Dispose();
+                        e.Throw();
+                    }
+
+                    //
+                    // If the periodic scheduling job already ran before we finished dispatching the OnNext(0L)
+                    // call, we'll find pendingTickCount to be > 1. In this case, we need to catch up by dispatching
+                    // subsequent calls to OnNext as fast as possible, but without running a loop in order to ensure
+                    // fair play with the scheduler. So, we run a tail-recursive loop in CatchUp instead.
+                    //
+                    if (Interlocked.Decrement(ref _pendingTickCount) > 0)
+                    {
+                        var c = new SingleAssignmentDisposable();
+                        c.Disposable = self.Schedule(1L, CatchUp);
+
+                        return StableCompositeDisposable.Create(d, c);
+                    }
+
+                    return d;
                 }
-                catch (Exception e)
+
+                private long Tock(long count)
                 {
-                    _periodic.Dispose();
-                    e.Throw();
+                    //
+                    // Notice the handler for (emulated) periodic scheduling is non-reentrant.
+                    //
+                    // When there's no overlap with the OnNext(0L) call, the following code will cycle through
+                    // pendingTickCount 0 -> 1 -> 0 for the remainder of the timer's execution.
+                    //
+                    // If there's overlap with the OnNext(0L) call, pendingTickCount will increase to record
+                    // the number of catch up OnNext calls required, which will be dispatched by the recursive
+                    // scheduling loop in CatchUp (which quits when it reaches 0 pending ticks).
+                    //
+                    if (Interlocked.Increment(ref _pendingTickCount) == 1)
+                    {
+                        base._observer.OnNext(count);
+                        Interlocked.Decrement(ref _pendingTickCount);
+                    }
+
+                    return unchecked(count + 1);
                 }
 
-                //
-                // We can simply bail out if we decreased the tick count to 0. In that case, the Tock
-                // method will take over when it sees the 0 -> 1 transition.
-                //
-                if (Interlocked.Decrement(ref _pendingTickCount) > 0)
+                private void CatchUp(long count, Action<long> recurse)
                 {
-                    recurse(unchecked(count + 1));
+                    try
+                    {
+                        base._observer.OnNext(count);
+                    }
+                    catch (Exception e)
+                    {
+                        _periodic.Dispose();
+                        e.Throw();
+                    }
+
+                    //
+                    // We can simply bail out if we decreased the tick count to 0. In that case, the Tock
+                    // method will take over when it sees the 0 -> 1 transition.
+                    //
+                    if (Interlocked.Decrement(ref _pendingTickCount) > 0)
+                    {
+                        recurse(unchecked(count + 1));
+                    }
                 }
             }
         }

+ 6 - 6
Rx.NET/Source/src/System.Reactive/Linq/Observable/Timestamp.cs

@@ -19,24 +19,24 @@ namespace System.Reactive.Linq.ObservableImpl
 
         protected override IDisposable Run(IObserver<Timestamped<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
         {
-            var sink = new _(this, observer, cancel);
+            var sink = new _(_scheduler, observer, cancel);
             setSink(sink);
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<Timestamped<TSource>>, IObserver<TSource>
+        private sealed class _ : Sink<Timestamped<TSource>>, IObserver<TSource>
         {
-            private readonly Timestamp<TSource> _parent;
+            private readonly IScheduler _scheduler;
 
-            public _(Timestamp<TSource> parent, IObserver<Timestamped<TSource>> observer, IDisposable cancel)
+            public _(IScheduler scheduler, IObserver<Timestamped<TSource>> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
+                _scheduler = scheduler;
             }
 
             public void OnNext(TSource value)
             {
-                base._observer.OnNext(new Timestamped<TSource>(value, _parent._scheduler.Now));
+                base._observer.OnNext(new Timestamped<TSource>(value, _scheduler.Now));
             }
 
             public void OnError(Exception error)

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

@@ -22,9 +22,9 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<TSource[]>, IObserver<TSource>
+        private sealed class _ : Sink<TSource[]>, IObserver<TSource>
         {
-            private List<TSource> _list;
+            private readonly List<TSource> _list;
 
             public _(IObserver<TSource[]> observer, IDisposable cancel)
                 : base(observer, cancel)

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

@@ -28,23 +28,25 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<IDictionary<TKey, TElement>>, IObserver<TSource>
+        private sealed class _ : Sink<IDictionary<TKey, TElement>>, IObserver<TSource>
         {
-            private readonly ToDictionary<TSource, TKey, TElement> _parent;
-            private Dictionary<TKey, TElement> _dictionary;
+            private readonly Func<TSource, TKey> _keySelector;
+            private readonly Func<TSource, TElement> _elementSelector;
+            private readonly Dictionary<TKey, TElement> _dictionary;
 
             public _(ToDictionary<TSource, TKey, TElement> parent, IObserver<IDictionary<TKey, TElement>> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _dictionary = new Dictionary<TKey, TElement>(_parent._comparer);
+                _keySelector = parent._keySelector;
+                _elementSelector = parent._elementSelector;
+                _dictionary = new Dictionary<TKey, TElement>(parent._comparer);
             }
 
             public void OnNext(TSource value)
             {
                 try
                 {
-                    _dictionary.Add(_parent._keySelector(value), _parent._elementSelector(value));
+                    _dictionary.Add(_keySelector(value), _elementSelector(value));
                 }
                 catch (Exception ex)
                 {

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

@@ -22,9 +22,9 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<IList<TSource>>, IObserver<TSource>
+        private sealed class _ : Sink<IList<TSource>>, IObserver<TSource>
         {
-            private List<TSource> _list;
+            private readonly List<TSource> _list;
 
             public _(IObserver<IList<TSource>> observer, IDisposable cancel)
                 : base(observer, cancel)

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

@@ -29,23 +29,25 @@ namespace System.Reactive.Linq.ObservableImpl
             return _source.SubscribeSafe(sink);
         }
 
-        class _ : Sink<ILookup<TKey, TElement>>, IObserver<TSource>
+        private sealed class _ : Sink<ILookup<TKey, TElement>>, IObserver<TSource>
         {
-            private readonly ToLookup<TSource, TKey, TElement> _parent;
-            private Lookup<TKey, TElement> _lookup;
+            private readonly Func<TSource, TKey> _keySelector;
+            private readonly Func<TSource, TElement> _elementSelector;
+            private readonly Lookup<TKey, TElement> _lookup;
 
             public _(ToLookup<TSource, TKey, TElement> parent, IObserver<ILookup<TKey, TElement>> observer, IDisposable cancel)
                 : base(observer, cancel)
             {
-                _parent = parent;
-                _lookup = new Lookup<TKey, TElement>(_parent._comparer);
+                _keySelector = parent._keySelector;
+                _elementSelector = parent._elementSelector;
+                _lookup = new Lookup<TKey, TElement>(parent._comparer);
             }
 
             public void OnNext(TSource value)
             {
                 try
                 {
-                    _lookup.Add(_parent._keySelector(value), _parent._elementSelector(value));
+                    _lookup.Add(_keySelector(value), _elementSelector(value));
                 }
                 catch (Exception ex)
                 {

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio