Обычно в реактивных расширениях любые необработанные исключения всплывают и обычно приводят к завершению программы, а ReactiveUI следует за этим, повторно генерируя исключения, если ThrownExceptions не подписан. Поэтому я был удивлен, увидев, что следующий пример кода (работает в RoslynPad) на самом деле не завершается:
#r "nuget:ReactiveUI/9.13.1"
using System.Reactive.Linq;
using ReactiveUI;
class ReactiveExample : ReactiveObject
{
public ReactiveExample()
{
var o = this.ObservableForProperty(x => x.S, skipInitial: true).Select(x => x.Value);
o.Subscribe(s =>
{
Console.WriteLine("received value " + s);
throw new Exception("throw on value " + s);
});
//this.ThrownExceptions.Subscribe(e => throw new Exception("uncaught", e));
}
public string S
{
get => _s;
set => this.RaiseAndSetIfChanged(ref _s, value);
}
private string _s = "";
}
var r = new ReactiveExample();
r.S = "bar";
Если вы подпишетесь на ThrownExceptions, оставив комментарий в соответствующей строке выше, ясно, что действительно создается исключение.
Это ошибка или особенность? Я считаю, что это вызвано попыткой / уловом в ReactiveUI.IReactiveObjectExtensions.NotifyObservable, которая, как я ожидал, повторно выбросит исключение в случае, если наблюдаемый объект ThrownExceptions не имеет подписчика, а не просто регистрирует его (см. из строки 382).