How to expose IObservable<T> properties without using Subject<T> backing field

c#, system.reactive

Solution

In an answer on the Rx forum, Dave Sexton (of Rxx), said as part an answer to something:

Subjects are the stateful components of Rx. They are useful for when you need to create an event-like observable as a field or a local variable.

Which is exactly what's happening with this question, he also wrote an in-depth follow up blog post on To Use Subject Or Not To Use Subject? which concludes with:

When should I use a subject?

When all of the following are true:

- you don't have an observable or anything that can be converted into one.

- you require a hot observable.

- the scope of your observable is a type.

- you don't need to define a similar event and no similar event already exists.

Why should I use a subject in that case?

Because you've got no choice!

So, answering the inner question of "details on why using Subject like this is a bad idea" - it's not a bad idea, this is one of the few places were using a Subject is the correct way to do things.

Problem

In this answer to a question about `Subject<T>` Enigmativity mentioned: as an aside, you should try to avoid using subjects at all. The general rule is that if you're using a subject then you're doing something wrong. I often use subjects as backing fields for `IObservable` properties, which would have probably been .NET events in the days before Rx. e.g. instead of something like ``` public class Thing { public event EventHandler SomethingHappened; private void DoSomething() { Blah(); SomethingHappened(this, EventArgs.Empty); } } ``` I might do ``` public class Thing { private readonly Subject<Unit> somethingHappened = new Subject<Unit>(); public IObservable<Unit> SomethingHappened { get { return somethingHappened; } } private void DoSomething() { Blah(); somethingHappened.OnNext(Unit.Default); } } ``` So, if I want to avoid using `Subject` what would be the correct way of doing this kind of thing? Or I should I stick to using .NET events in my interfaces, even when they'll be consumed by Rx code (so probably `FromEventPattern`)? Also, a bit more details on why using `Subject` like this is a bad idea would be helpful. Update: To make this question a bit more concrete, I'm talking about using `Subject<T>` as a way to get from non-Rx code (maybe you're working with some other legacy code) into the Rx world. So, something like: ``` class MyVolumeCallback : LegacyApiForSomeHardware { private readonly Subject<int> volumeChanged = new Subject<int>(); public IObservable<int> VolumeChanged { get { return volumeChanged.AsObservable(); } } protected override void UserChangedVolume(int newVolume) { volumeChanged.OnNext(newVolume); } } ``` Where, instead of using events, the LegacyApiForSomeHardware type makes you override virtual methods as a way of getting "this just happened" notifications.

Original source

Related problems