5

我有一个行为主题

var source = new BehaviorSubject<int>(0);

然后我用类似的东西处理那个源

var withErrors = source
            .Select(v =>
            {
                if (v == 2)
                {
                    throw new Exception("Ouch ");
                }
                return v;
            })

我想以可以跳过错误的方式订阅 withErrors。像这样的 catch 尝试。

public IObservabe<int> SkipError(IObservable<T> source){

    return source
       .Catch(e=>SkipErrors(source.Skip(1));
}

然后这样称呼它

var withoutErrors = SkipError(withErrors);

Skip 是为了避免在行为主题上重复最后一个错误,但可惜它不是那样工作的。Skip 不会跳过错误,而只会跳过有效数据,因此行为主题中当前状态的错误会不断通过。

是否有一种聪明的方法来编写 Skip 也会跳过错误。有些东西告诉我这是不可能的,但希望我错了

4

1 回答 1

2

由于问题的前提是错误的,我提出了better一种使用Exceptional<T>monad 的方法。例如

IObservable<int> source = ....;
IObservable<Exceptional<string>> withErrors =
    source.Select(i=>Exceptional.Execute(()=>{
        if(v==2){
            throw new Exception("Ouch");
        }
        return v.ToString();
    });


IObservable<Exception> errors = 
    withErrors.Where(v=>v.HasException).select(v=>v.Exception);

IObservable<string> values =
    withErrors.Where(v=>!v.HasException).select(v=>v.Value);

只是为了好玩,你可以做

Exceptional<string> r = 
         from x in Exceptional.Execute(() => "xxx")
         from y in Exceptional.Execute(() => "zzz")
         select x + y;

这将生成一个异常值“xxxzzz”。如果任何步骤确实引发了异常,那么它将短路并仅保留异常。

我基于另一个 SO 答案的实现是https://gist.github.com/bradphelan/6154972

于 2013-08-05T10:58:06.860 回答