// The callers (Last/LastOrDefault) are blocking methods. static TSource InternalLastOrDefault <TSource> (this IObservable <TSource> source, Func <TSource, bool> predicate, bool throwError) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } var wait = new HybridWait(); TSource ret = default(TSource); bool got = false; var dis = source.Subscribe( // the first "if (!got) check is required because the source may send next values before unsubscribing this action by dis.Dispose(). (s) => { if (predicate(s)) { got = true; ret = s; } }, () => { wait.Set(); } ); wait.WaitOne(); dis.Dispose(); if (!got && throwError) { throw new InvalidOperationException(); } return(ret); }
// The callers (Single/SingleOrDefault) are blocking methods. static TSource InternalSingleOrDefault <TSource> (this IObservable <TSource> source, Func <TSource, bool> predicate, bool throwError) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } var wait = new HybridWait(); TSource ret = default(TSource); bool got = false, error = false; IDisposable dis = null; dis = source.Subscribe( // the first "if (!got) check is required because the source may send next values before unsubscribing this action by dis.Dispose(). s => { if (predicate(s)) { if (got) { error = true; } got = true; ret = s; } }, () => wait.Set() ); wait.WaitOne(); dis.Dispose(); if (error) { throw new InvalidOperationException("Observed that there was more than one item in the target object"); } if (!got && throwError) { throw new InvalidOperationException(); } return(ret); }