Effective C# 第5章

Effective C# 6.0/7.0 | Bill Wagner, 鈴木 幸敏, 鈴木 幸敏 |本 | 通販 | Amazon

個人的な読書ノートであり、自分の解釈が誤っていたり要点がずれてる可能性があります。内容が気になる人は自分で読んでください。

読了!

5章 例外処理

要求された処理が実行できない場合には常に例外をスローするべき

45. 契約違反を例外として報告すること

  • 正しく実行できない場合に例外をスローして失敗を報告する
  • 例外をフロー制御のために使用してはいけない
  • フロー制御に使われないためにも、テスト用のメソッドも提供するべき
  • DoWork, TryDoWork パターン

46. using および try...finally を使用してリソースの後処理を行う

  • IDisposableに using を使うとコンパイラtry...finally ブロックを生成する
  • using (obj as IDisposable) {...} というテク
  • リソース確保は using内または tryブロック内で行うこと

47. アプリケーション固有の例外クラスを作成する

  • 例外を発生させた問題に対して、異なる対応が必要になることが確実である場合のみ別の例外を用意するべき
  • 起こり得るすべてのエラー状態にたいして例外を用意する必要はない
  • エラーを修正できるような情報を含んだ独自の例外クラスを作成する
  • Exceptionクラスは4つ全てのコンストラクタを定義するべき
  • InnerException をつかって下位のエラーを上位に伝える

https://hackers-high.com/c-sharp/develop-self-exception/

48. 例外を強く保証すること

  • 例外安全保証レベル
    • 基本的な例外保証: リソースリークを発生させず、すべてのオブジェクトが正しい状態であり続けることを保証
    • 強い例外保証: 基本的な例外保証 + 例外のスロー後もプログラムの状態が変化しないことを保証
    • 例外をスローしない保証: 例外をスローさせないようにすることですべての操作が失敗しないことを保証
  • 強い例外保証:処理が完了するか、そうでなければ何も起こらないようにする。
  • オブジェクトのコピーコストはマネージ環境ではほとんど無視できる。
  • 例外によってプログラムが強制終了する場合強い例外保証をする意味はない。
  • Envelope/Letterパターンで、内部データ入れ替え処理を1つのオブジェクトに隠蔽できる。
  • when 句で例外をスローしてはいけない。
  • デリゲートに登録されるメソッドの中で例外をスローしてはいけない。

オブジェクトのコピーコストはマネージ環境ではほとんど無視できる

信じられない。

このためだけにEnvelope/Letterパターン使うの記述量が多すぎる全然便利に思えない。

49. catch からの再スローよりも例外フィルタを使用すること

  • catch 句に条件ロジックを追加するのではなく、例外フィルタ(when) を実装するべき。
  • catch (TimeoutException e) when (retryCount++ < 3)
  • スタック巻き戻しが起こる前に例外フィルタが評価されるのでエラー情報をより多く確保できる。

50. 例外フィルタの副作用を活用する

  • 例外フィルタで常に false を返すようにして、すべての例外のログを残すことができる。
  • デバッグ実行中はcatchしないようにすることもできる。
  • try ブロック内の変数が残った状態デバッガにアタッチできてデバッグが捗る。
public static bool ConsoleLogException(Exception e)
{
    WriteLine("エラー{0}", e);
    return false;
}

try {}
catch (Exception e) when (ConsoleLogException(e)) {} // すべての例外のログを残せるテク
catch (TimeoutException e) when ((failures++ < 10) &&
  (!System.Diagnostics.Debugger.IsAttached)){ ... } // デバッグ実行中はcatchしないテク

これはいいことを知った。早速使っていこう。