Перегрузка Publish<TSource, TResult>(Func<IObservable<TSource, IObservable<TResult>> selector)
плохо документирована.Ли Кэмпбелл не покрывает это в introtorx.com .Он не возвращает IConnectableObservable
, то есть то, что большинство людей ассоциирует с Publish
, и поэтому не требует или не поддерживает Connect
или RefCount
вызов.
Эта форма Publish
в основном является формой защитного кодирования от возможных побочных эффектов в наблюдаемом источнике.Он подписывается один раз на источник, а затем может безопасно «рассылать» все сообщения через переданный параметр.Если вы посмотрите на код вопроса, там только один раз упоминается source
и два упоминания _source
._source
здесь - безопасная многоадресная наблюдаемая, source
- небезопасная.
В приведенном выше примере источник - это простой Subject
, поэтому он не является на самом деле небезопасным, и поэтому Publish
имеетнет эффекта.Однако, если вы замените source
на это:
var source = Observable.Create<int>(o =>
{
Console.WriteLine("Print me once");
o.OnNext(1);
o.OnNext(2);
o.OnNext(3);
o.OnNext(4);
return System.Reactive.Disposables.Disposable.Empty;
});
... вы обнаружите, что «Напечатать меня один раз» напечатано один раз с pairs
(правильно) и дважды с pairs2
.Этот эффект имеет аналогичные последствия, когда ваша наблюдаемая оболочка включает в себя такие вещи, как запросы к БД, веб-запросы, сетевые вызовы, чтение файлов и другой побочный код, который вы хотите выполнить только один раз, а не несколько раз.
TL; DR: Если у вас есть наблюдаемый запрос, который дважды ссылается на наблюдаемый, лучше всего обернуть этот наблюдаемый в вызов Publish
.