気軽に楽しくプログラムと遊ぶ

自分が興味があってためになるかもって思う情報を提供しています。

try-catchとrunCatching foldの違いとメリデメ

try-catchとrunCatching foldの違い

try-catchとは

try-catchはKotlinの言語機能として提供される例外処理機構である。tryブロック内で例外が発生する可能性のあるコードを実行し、catchブロックで例外を捕捉して処理する。finallyブロックを追加すれば、例外の発生に関わらずクリーンアップ処理を実行できる。例外はuncheckedのみで、コンパイル時にチェックされない。

runCatchingとfoldとは

runCatchingはKotlin標準ライブラリの関数で、指定されたブロックを実行し、成功時は結果をResultオブジェクトに封装して返す。失敗時はThrowableを捕捉し、Result.failureとして返す。foldはResultオブジェクトのメソッドで、onSuccessとonFailureのラムダを指定して成功時と失敗時の処理を定義する。これにより関数型スタイルで例外を扱える。

実装例

try-catchの実装例

以下は、整数除算でゼロ除算例外を扱う例である。

fun divide(a: Int, b: Int): Int {
    try {
        return a / b
    } catch (e: ArithmeticException) {
        println("ゼロ除算エラー: ${e.message}")
        return 0
    } finally {
        println("処理終了")
    }
}

// 使用例
val result = divide(10, 0)  // 出力: ゼロ除算エラー: / by zero, 処理終了, result=0

runCatching foldの実装例

同じ整数除算を関数型スタイルで扱う例である。

fun divide(a: Int, b: Int): Result<Int> = runCatching { a / b }

val result = divide(10, 0).fold(
    onSuccess = { it },
    onFailure = {
        println("ゼロ除算エラー: ${it.message}")
        0
    }
)

// 出力: ゼロ除算エラー: / by zero, result=0

違い

try-catchは構造化された制御フローで、特定の例外タイプを複数catchブロックで扱える。finallyでリソース解放を保証する。一方、runCatchingはすべてのThrowableを捕捉し、Resultとして値を返すため、エラーをデータとして伝播可能。foldはResultを展開して処理を分岐させる。try-catchは即時処理向きで、runCatching foldはエラー遅延処理やチェーンに適する。

比較表

項目 try-catch runCatching fold
スタイル 命令型。制御フローで例外を即時処理。 関数型。Resultオブジェクトでエラーを値として扱い、遅延処理可能。
例外捕捉 特定の例外タイプを複数catchで指定可能。 すべてのThrowableを捕捉。特定の例外はfold内で分岐。
クリーンアップ finallyブロックで確実。 直感的でない場合あり。onFailure内で処理するか、別途実装。
コードの簡潔さ ボイラープレートが増えやすい。 簡潔でチェーン可能。
親和性 伝統的なプログラミングに適する。 関数型プログラミングやコルーチンに強い。
パフォーマンス 言語機能のため効率的。 Resultオブジェクト生成で若干オーバーヘッド。

try-catchのメリット・デメリット

メリット

  • 標準的で読みやすい。特定の例外を細かく扱える。
  • finallyブロックでクリーンアップを確実に実行可能。
  • 言語機能のため、ライブラリ依存がない。

デメリット

runCatching foldのメリット・デメリット

メリット

  • 簡潔で関数型。Resultを返してエラーを値として扱える。
  • チェーン可能で、遅延処理向き。
  • コルーチンや非同期処理でエラーを柔軟に伝播。

デメリット

  • すべての例外を捕捉するため、意図しないエラーを隠蔽しやすい。
  • finallyのようなクリーンアップが直感的でない場合がある。
  • パフォーマンスがtry-catchより劣る可能性。

参照サイト