Catch
1. 概要
Catch は、ソース Observable が致命的エラー(OnCompleted(Result.Failure))で完了した際に、代替の Observable に切り替えてシーケンスを継続するオペレーターです。ソースが正常に完了した場合、代替 Observable は使用されません。
2. シグネチャ
固定の代替 Observable を指定するオーバーロード
csharp
public static Observable<T> Catch<T>(
this Observable<T> source,
Observable<T> second)ソースが失敗で完了した場合、事前に指定した second Observable を購読して後続の要素を発行します。エラーの内容に関わらず、常に同じ代替シーケンスが使用されます。
例外に応じて代替 Observable を生成するオーバーロード
csharp
public static Observable<T> Catch<T, TException>(
this Observable<T> source,
Func<TException, Observable<T>> errorHandler)
where TException : Exceptionソースが失敗で完了した場合、例外オブジェクトを errorHandler に渡し、返された Observable を購読します。例外の型や内容に応じて異なるリカバリ処理を行いたい場合に使用します。TException で型フィルタリングが可能で、一致しない例外型の場合はそのまま失敗として伝播します。
オーバーロード の使い分け
| オーバーロード | 使用場面 |
|---|---|
Catch(source, second) | フォールバック先が固定で、エラーの種類を問わずに代替シーケンスに切り替えたい場合 |
Catch(source, errorHandler) | エラーの型・内容に応じて動的にリカバリ先を決定したい場合 |
3. マーブルダイアグラム
ソースシーケンスが致命的エラー(OnCompleted(Result.Failure))で終了すると、代替 Observable への購読が開始され、代替シーケンスの要素がそのまま流れます。ソースが正常に完了した場合は、代替 Observable は購読されずにそのまま完了します。
4. サンプルコード
固定の代替 Observable による基本的なフォールバック
csharp
using R3;
// メインソースが失敗した場合にフォールバック値を返す
var fallback = Observable.Return("default-value");
var source = Observable.Create<string>(observer =>
{
observer.OnNext("data-1");
observer.OnNext("data-2");
// 致命的エラーで完了
observer.OnCompleted(Result.Failure(new InvalidOperationException("接続失敗")));
return Disposable.Empty;
});
source
.Catch(fallback)
.Subscribe(
value => Console.WriteLine($"値: {value}"),
result => Console.WriteLine($"完了: {result}")
);
// 出力:
// 値: data-1
// 値: data-2
// 値: default-value
// 完了: Success例外の型に応じたリカバリ処理
csharp
using R3;
var source = Observable.Create<int>(observer =>
{
observer.OnNext(1);
observer.OnCompleted(Result.Failure(new TimeoutException("タイムアウト")));
return Disposable.Empty;
});
source
.Catch((TimeoutException ex) =>
{
Console.WriteLine($"タイムアウト発生: {ex.Message}、キャッシュに切り替え");
return Observable.Create<int>(observer =>
{
observer.OnNext(-1); // キャッシュ値
observer.OnCompleted();
return Disposable.Empty;
});
})
.Subscribe(
value => Console.WriteLine($"値: {value}"),
result => Console.WriteLine($"完了: {result}")
);
// 出力:
// 値: 1
// タイムアウト発生: タイムアウト、キャッシュに切り替え
// 値: -1
// 完了: Success5. 補足
IgnoreOnErrorResume との比較
Catch と IgnoreOnErrorResume はどちらもエラーハンドリングオペレーターですが、対象とするエラーの種類が異なります。
| 特性 | Catch | IgnoreOnErrorResume |
|---|---|---|
| 対象エラー | 致命的エラー (OnCompleted(Result.Failure)) | 非致命的エラー (OnErrorResume) |
| 動作 | 代替 Observable に切り替える | エラー通知を無視して継続する |
| シーケンスの継続 | 代替シーケンスとして継続 | 同一シーケンスが継続 |
両者を組み合わせることで、非致命的エラーは無視しつつ致命的エラーにはフォールバックで対処する、といった堅牢なエラーハンドリングパイプラインを構築できます。