C# の例外メモ

乱暴なまとめ

  • ある一連の処理が、その過程で継続不能な状態に陥ったことを、呼び出し元に伝えるための機能。
  • 呼び出し元に対して伝えることになるので『お前の○○が悪い』という内容の通達になる。
    • お前の用意した引数に問題がある。
  • 自分ではどうしようもない例外は catch してはいけないし、自分で管理していないリソースに関する例外を投げてもいけない。

文法

  • try 文の中で例外が発生すると catch 文に飛ぶ。
  • catch 文は複数書くことができる。
  • try 文が無事に成功しても、失敗しても必ず finally 文は最後に実行される。
try
{
    // try 文
}
catch (NotImplementedException ex)
{
    // catch 文 その1

}
catch (Exception ex)
{
    // catch 文 その2
}
finally
{
    // finally 文
}

例外の投げ方の方針

  • 処理が継続不能になったことを理由を含めて呼び出し元に伝える
    • お前(呼び出し元)の引数 null やん・・・処理できひんし・・・
    • お前の引数、型はあってるけど、値がおかしいし・・・
  • 自分が管理しているわけではないリソースに関する例外は投げてはいけない
    • それは、.net Framework などのリソースを管理している人が投げるべき
    • OutOfMemoryException など
  • 例外は、役割分担を壊さない範囲で、なるべく呼び出し元に近いところで出すべき

例外の処理し方の方針

  • 自分ではどうしようもない例外は catch しない
    • OutOfMemoryException とか
  • 例外を catch したら、後始末を行う
    • リトライする
      • 規定された回数まで、失敗した処理を再試行する。
    • 規定値にする
      • うまくいかなかった時の規定値が決まっているのであれば、代わりにそれを返す。
    • 別の手段を試す
      • 他にうまくいくかもしれない手法があるならそちらを試す
    • エラーを返す・失敗させる
      • 出来なかった旨を伝え処理を終了する
    • 中止する
      • そこまでに、行ってしまった処理を戻して、その旨を伝える

投げるべき例外

ArgumentNullException

  • 関数の冒頭で、引数チェックを行い、 null ではダメな引数に null が入っていたら投げる
  • 例外の引数の message には、問題となっている引数の名前を入れることが多い

ArgumentOutOfRangeException

  • 関数の冒頭で、引数チェックを行い、処理できる範囲外の値が入っていた場合に投げる
  • null の場合は ArgumentNullException が優先される
  • 例外の引数の message には、問題となっている引数の名前を入れることが多い

InvalidOperationException

ObjectDisposedException

  • 既に Dispose されている IDisposable オブジェクトにアクセスしたとき
  • オブジェクトの Dispose の管理はあなたが行うため

FileNotFoundException, DirectoryNotFoundException

  • 引数で与えられたファイルやディレクトリが存在しなかった場合に投げる

FormatException

  • 引数で与えられたフォーマットがおかしかった場合に投げる

TimeoutException

  • 何がしかの処理がタイムアウトした際に投げる

NotImplementedException

  • 未実装のメソッドで投げる
  • 早く実装しよう

投げてはいけない例外

.net Framework のリソースに関するもの

  • StackOverflowException, OutOfMemoryException など
  • .net Framework が管理するリソースのため

NullReferenceException, DivideByZeroException

  • おかしな値で処理を試みるべきではないので、引数のチェックを行い、引数に関する例外を投げるべき
  • そもそも、引数のチェックをしていれば出るはずはない

InvalidCastException

参考資料