[基礎知識]例外処理について

一般的な例外処理を以下にまとめてみました。
コードを書く上で参考にしてみて下さい。

1.例外処理の基礎

Dartでは、プログラムの実行中に予期しないエラーが発生した場合に、例外を投げる(スローする)ことができます。
これにより、エラーをキャッチして適切に処理することができます。例外処理の基本的な構文は try-catchブロックです。

(1) try-catch 構文

try-catch 構文を使って例外をキャッチし、処理する方法を説明します。

try-catch 構文:
void main() {
  try {
    int result = 10 ~/ 0; // 例外が発生する行
  } catch (e) {
    print('例外が発生しました: $e'); // 例外をキャッチして処理
  }
}

上記の例では、10 ~/ 0という整数の割り算が実行され、ゼロ除算例外が発生します。
catchブロックでこの例外をキャッチし、エラーメッセージを表示します。

補足:

try – catch を追記した場合、以下の様な点には注意して下さい。

⓵ try ブロックで、何かを return している場合

Dart
Future<void> _cateDialogBuilder(BuildContext context) async {
  try {
    // showDialogがFutureを返すので、この値を直接returnしても良いです。
    return showDialog<void>(

  ・・・(省略)・・・
  
  } catch (e) {
    if (kDebugMode) {
      print('_cateDialogBuilder例外発生:$e');
    }
    // 例外が発生した場合は、Future<void>を返すためにFutureを完了させます。
    return Future.error(e);
  }
}

catch ブロックでも必ず何かしらの値を返すようにしましょう。

(2) finally ブロック

try-catch 構文には、必ず実行されるfinally ブロックを追加することができます。
これは、例外が発生してもしなくても実行されるコードを記述するために使用します。

finally ブロック:
void main() {
  try {
    int result = 10 ~/ 0; // 例外が発生する行
  } catch (e) {
    print('例外が発生しました: $e'); // 例外をキャッチして処理
  } finally {
    print('このブロックは常に実行されます'); // 例外の有無に関わらず実行
  }
}

2.カスタム例外

自分で定義したカスタム例外を投げることもできます。

カスタム例外:
class CustomException implements Exception {
  final String message;
  CustomException(this.message);

  @override
  String toString() => 'CustomException: $message';
}

void main() {
  try {
    throw CustomException('これはカスタム例外です');
  } catch (e) {
    print(e); // CustomException: これはカスタム例外です
  }
}

3.例外の伝播とrethrow

キャッチした例外を再度投げる場合には、rethrow キーワードを使用します。

例外の伝播と rethrow:
void main() {
  try {
    someFunction();
  } catch (e) {
    print('上位でキャッチ: $e');
  }
}

void someFunction() {
  try {
    throw Exception('例外発生');
  } catch (e) {
    print('内部でキャッチ: $e');
    rethrow; // 例外を再度スロー
  }
}

4.非同期処理の例外処理

非同期関数で例外をキャッチする方法です。

非同期処理の例外処理:
Future<void> main() async {
  try {
    await someAsyncFunction();
  } catch (e) {
    print('非同期関数でキャッチ: $e');
  }
}

Future<void> someAsyncFunction() async {
  await Future.delayed(Duration(seconds: 1));
  throw Exception('非同期例外');
}

5.例外処理のベストプラクティス

(1) 具体的な例外をキャッチする

具体的な例外タイプをキャッチすることで、特定のエラーに対する対処がしやすくなります。

具体的な例外をキャッチする:
void main() {
  try {
    int result = 10 ~/ 0;
  } on IntegerDivisionByZeroException {
    print('ゼロによる除算が発生しました');
  } catch (e) {
    print('その他の例外: $e');
  }
}

(2) 適切なログを残す

例外が発生した場合に適切なログを残しておくことで、後で問題を特定しやすくなります。

適切なログを残す:
void main() {
  try {
    int result = 10 ~/ 0;
  } catch (e, stackTrace) {
    print('例外が発生しました: $e');
    print('スタックトレース: $stackTrace');
  }
}

(3) 再スローの使用を注意深

例外を再スローする場合は、その例外を上位で適切に処理することを忘れないようにします。

再スロー(rethrow):
void main() {
  try {
    someFunction();
  } catch (e) {
    print('上位でキャッチ: $e');
  }
}

void someFunction() {
  try {
    throw Exception('例外発生');
  } catch (e) {
    print('内部でキャッチ: $e');
    rethrow;
  }
}

コメントを残す