569274 (1) [Avatar] Offline
#1
Page 91 of the book has an example where Disposable.Empty is getting returned in Subscribe method.

If I want to return a proper Disposable which will actually lead to unsubscribing when Dispose is called what should be the way? This is mostly an academic question as I use the built in helper methods.

I had a crack at it using this for the Observable https://docs.microsoft.com/en-us/dotnet/standard/events/how-to-implement-a-provider and this for Observer https://docs.microsoft.com/en-us/dotnet/standard/events/how-to-implement-an-observer

I had to introduce a subscription handler
public class SubscriptionHandler : IDisposable
{
	private readonly List<IObserver<int>> _listOfObservers;
	private readonly IObserver<int> _currentObserver;

	public SubscriptionHandler(List<IObserver<int>> currentListOfObservers, IObserver<int> currentObserver)
	{
		_listOfObservers = currentListOfObservers;
		_currentObserver = currentObserver;
	}

	public void Dispose()
	{
		if (_currentObserver != null && _listOfObservers.Contains(_currentObserver))
		{
			_listOfObservers.Remove(_currentObserver);
		}
	}
}


This is the code for the Observable
public class MyObservable : IObservable<int>
{
	private List<IObserver<int>> _listOfSubscribedObservers = new List<IObserver<int>>();

	public IDisposable Subscribe(IObserver<int> observer)
	{
		if (!_listOfSubscribedObservers.Contains(observer))
		{
			_listOfSubscribedObservers.Add(observer);
		}

		Task.Run(() =>
		{
			for (int i = 0; i < 5; i++)
			{
				Thread.Sleep(1000);
				observer.OnNext(i);
			}

			observer.OnCompleted();
		});

		return new SubscriptionHandler(_listOfSubscribedObservers, observer);
	}
}


Is there a built in way to return a meaningful Disposable for handcrafted Observable or this is something which comes only with Observable create helper methods.
Yeah69 (4) [Avatar] Offline
#2
The book explicitly states "Creating observables this way isn't the best practice, but I believe it's essential for understanding the mechanics of how observables work." directly before the example which you are referring to. In this example the whole sequence of the observable is implemented iteratively into the Subscribe-function including the OnCompleted-call. The OnCompleted-call already signals to the observer that the observable is done. The observer isn't cached as a field or in a list inside of the observable. Because the sequence is complete at the end of the Subscribe-function and there is nothing to dispose, it is legit in this very example to just return an Disposable.Empty which does nothing. As soon as the Subscribe-function returns everything is over and there is actually nothing to do anymore. Whether you dispose the subscribtion or not makes no difference here.

I didn't implement IObservable myself for a long time now. However, in a more "real-world" example, the returned disposable would dispose of the ongoing subscribtion (which is cached in some way) and dispose everything required to be disposed on unsubscribtion.