C#での例外とifの使い分け

この前、作業中にC#での例外について調べていた。最近の意識としては、投げるべきところで投げる例外は、必ず後々役に立つということ。

では逆に、投げるべきところではない場面とは一体どういうことだろうか。今回は、投げるべき場面と、そうでない場面。実体験と人から聞いた話に基づいて、つらつらと書き連ねていこうと思う。

まず、どこかの掲示板で「例外とifでのエラー処理の使いわけ」見たいな議論がされているものを見つけた(面白かったから、15レスくらいのを全部読んでしまったんだが、不覚にもURLを取り忘れてた。履歴もすぐ破棄されるPortableSleipnir環境だった、無念)。そこで得られた意見を、適当に集約していく。

エラーを知らせる対象は誰ですか?

その掲示板の中で、これについて言及している発言者が多かったように記憶している。今まで一人で開発してきて、他人と協力してプログラムを作成したことないという人は、なにやらイメージが沸きずらいかもしれない。要は、異常であることを知らせる対象が、

  • 開発者
  • 使用者(ユーザ)

のどちらであるか、ということである。例外というのは、元々予期されないエラーを拾うための機構なはず。ということは、本来起きてはいけない処理を、使用者に対して晒してしまって良いのかということで、これにはたとえば、ユーザの入力した値に不備がある場合などが挙げられる。こういうときは、やはり、入力された値に不備があるかどうかを疑う必要があるのであり、それは予期されたものだと考えられる。

一方、開発者に対してもやはりifを用いたエラー回避を行うべきだろうか。これは非常に考えどころだと思うが、開発者に対して「あなたの行っているその処理は、間違ったものである」ということを明確に知らせる必要があるから、ここには例外が適しているのではないかという意見があった。例外が起こると、デバッグ中に「おっ」と身を乗り出してしまうのは、プログラマーの常であろう。そう考えると、確かに納得できないでもない。

どちらの処理が重たい/軽いですか?

この切り口も、ありだとおもう。

tryするだけなら、ifと比べてもそれほどオーバーヘッドは変わらないらしい。ところが、catchするときに、結構なオーバーヘッドになるみたいだ。例外が発生することが明らかに分かるような処理はさせないほうが身のためだと思う。

Bitmapか何かの探索を行うとき、要素数チェックが面倒だからと、例外が起きるまでループさせて、起こったらそこで探索をやめるという処理を、何度も行うプログラムを書いている友人が居た。つまり、例外が起きることが前提な処理であり、「例外を握りつぶしている」のである。これをifで、きちんと境界チェックをしたところ、恐ろしい速度の変化があったそうだ(当たり前か)。

例外を握りつぶして良いものですか?

先ほどの話題の中で少し触れたが、例外を握りつぶすのが、どれだけ恐ろしい行為か。わざわざ異常であることを教えてくれているのに。

C#はcatchで例外の発生をキャッチすることができる。それと同時に、例外のインスタンスへの参照も得ることが出来る。

catch(Exception ex)
{
	//こうやって例外内容を出力するのが一般的だと思う。
	Console.WriteLine(ex.ToString());
}
catch(Exception)
{
	//ところが、こうやって握りつぶすこともできる。
	Console.WriteLine("握りつぶすこともできる。");
}

感想

今までの自分のコードを見てみると、例外を自分で投げるなど、思いつきもしなかったような頃のコードだ。例外を投げることが、有効なものであるということを理解して、きちんと例外を投げていくようなコードを書けるようになりたいものである。

コメントを残す

メールアドレスが公開されることはありません。