ゆうなんとかさんの雑記帳的な。

Twitterで踊ったり音ゲーしたりしてるあの名前がよくわからない人が書いてるらしいよ。

例外についてちょっと調べてみた

例外処理は構文こそ知っているものの、どう書くといいのか今まであまりよく考えてませんでした。

まずはおさらい

いまさらですが例外の書き方をおさらいしておきましょう。

try
{
  例外が起きるかもしれない作業
}
catch (SomeException ex)
{
  SomeExceptionが起きたときの処理
}
catch (Exception ex)
{
  Exceptionが起きたときの処理
}
Finally
{
  例外処理も含めて処理が終わった時に実行する作業
}

C#の場合、例外の情報が特に必要ないときは例外クラスだけ書いておくようにすることもできます。例外が起きるとcatchされるまでコールスタックを順にたどっていって、どこでもcatchされなければアプリケーションが異常終了します。この時に吐いた例外はOSのイベントログから見ることができます。

例外は正しく中継しましょう

catchした例外をthrowするときに、

catch (SomeException ex)
{
  // 例外処理
  throw ex; //スタックトレースがリセットされる
}

上のように例外変数をthrowするとスタックトレースがリセットされてしまうそうです。よほどのことがない限りは、新しい例外変数を作ってthrowするか、変数を与えずにthrowするかのどちらかを選んだほうがいいですね。

例外をなるべく発生させないために

基本的に例外のハンドリングは普通の処理より負荷がかかります。なので、なるべくなら例外は起きないようにしたいものです。nullチェックなんかは簡単にできる割にはよく出くわす例外ですが、こういうときはTester-Doerパターン、またはTryParseパターンというのを使うそうです。Tester-Doerパターンは二度手間になりますが、例外を起こすよりはコストが低いです。
Tester-Doerの例

if (hoge == null)
{
  //何もしないでreturn、hogeに規定値を与えるなど…
}
// hogeに対する処理

TryParseパターンはやや不恰好ですが、こんな感じで使います。
int value = 0;
if (int.TryParse(input, out value))
{
// パースに成功したとき
}
else
{
// パースに失敗したとき
}
refとかoutとか、たぶんこういうときのほかはP/Invokeのときにしか使わないのが身のためです。

例外の使い方について

ここが参考になります。使い方はいたってシンプルで、「想定外のことが起きたら例外を投げる」という感じでいいそうです。そうはいってもなかなか難しいんですけどね。
http://ufcpp.net/study/csharp/misc_exception.html;title