为什么没有只带错误处理程序的订阅重载?

4

IObservable提供了Next、Next+Error、Next+Complete、Next+Complete+Error的订阅重载,但为什么没有只针对错误的observable呢?

我猜是因为可能存在Exception的IObservable,这会导致冲突,例如:

IObservable<Exception> obs;
obs.Subscribe(ex => { });

RX 不知道你是订阅 Next 还是 Error。

有没有一种只订阅错误的方式而不创建空的完成委托?

obs.Subscribe(
    o => { },
    ex =>
    {
        // error-handling-code
    });

1
根据您相关的问题,似乎您想要观察一系列异常,但OnError只能给您一个异常...就像Nenad所说的那样。而且您已经接近了...您需要一个IObservable<Exception>或Subject<Exception>,并使用OnNext,而不是OnError。当您的IObservable<Exception>有异常时,OnError才会被调用,而不是在流本身上。希望这可以帮助到您。 - Richard Anthony Freeman-Hein
2个回答

6

好的,这似乎是一个知识性问题,因此:

从C#编译器的角度来看,对于IObservable方法签名,您提出的建议将是(考虑到T = Exception):

public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext);
public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onError);

两种方法重载的签名是相同的,编译器不支持。

从接口的角度来看,你定义了如下的IObserver:

public interface IObserver<in T>
{
    void OnCompleted();
    void OnError(Exception error);
    void OnNext(T value);
}

接口的实现应该像这样:

public class Observer<T> : IObserver<T>
{
    public void OnCompleted()
    {
    }

    public void OnError(Exception error)
    {
        // Do something with exception
    }

    public void OnNext(T value)
    {
    }
}

因此,即使您不指定OnNext =()=> {},基础架构也必须实现它。 指定它不会使性能下降。
从观察者模式的逻辑角度来看,您的意图是异步订阅元素/事件序列。省略OnNext函数仅保留OnError的方法签名将误导Rx库的用户。如果您明确声明您不想在OnNext上执行任何操作,则更加清晰。
引用:一旦收到OnCompleted或OnError方法,Rx语法保证可以认为订阅已完成。
您尝试的操作相当于创建一个空的foreach循环并等待异常:
try
{
    foreach (var e in sequence)
    {
        // do nothing
    }
}
catch (Exception ex)
{
    // Do something
}

这并不是常见的情况。

1
这非常有帮助,谢谢。考虑到 IObservable 的整个目的是接收对象流,因此当接收这些对象时,您必须明确指定希望执行“无操作”。在我的代码中,我当然会处理 OnNext 调用,但我只想在另一个区域的代码中单独处理异常,在那里我将汇集多个潜在的异常源,并可能使用 Amb 来获取第一个到达的异常。然而,我现在在想,对于这种特定的用例,IObservable<Exception> 是否更合适。 - NoPyGod

1
我认为这是你忽略的问题:
一旦收到了OnCompletedOnError方法,Rx语法保证订阅可以被视为已完成。
如果您只关心终止操作的异常,那么需要使用try-catch。
如果您关心异常序列,则必须捕获它们并使用observer.OnNext(ex)返回,而不是使用observer.OnError中断订阅。

不,我没有忽略那个,而且我认为它甚至不相关。而且,try catch也完全无法帮助。 - NoPyGod
使用Observable可以异步地订阅序列。在您的示例中,您根本不关心序列,只关心一个异常。您有使用Observable的有效理由吗? - Nenad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接