4

IObservable 具有 Next、Next+Error、Next+Complete、Next+Complete+Error 的 Subscribe 重载,但为什么只有 Errors 没有 observable 呢?

我认为这是因为可能存在异常的 IObservable 并且它会导致冲突,即:

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

RX 不会知道您订阅的是 Next 还是 Error。

有没有办法单独订阅错误而不创建空的 Complete 委托?

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

2 回答 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
}

这不是常见的情况。

于 2013-02-16T11:51:51.747 回答
1

我认为这是您忽略的:

一旦接收到OnCompletedorOnError方法,Rx 语法保证订阅可以被认为是完成的。

  1. 如果您只关心将终止操作的异常,try-catch 就是您所需要的。
  2. 如果您关心异常序列,则必须使用 捕获它们并返回observer.OnNext(ex),而不是使用 中断订阅observer.OnError
于 2013-02-16T01:23:11.413 回答