2010年09月29日

try-catchのスタイル

   このエントリーをはてなブックマークに追加 Clip to Evernote
やねうらおさんとこの「C#のvarとtry〜catchが糞すぎる」の記事を読んで思ったこと。

は、確かに、if 文が余分なので、初心者が書くコードなのかもしれないですが、
new をtry の外に出すこと自体は、間違っていないと考えています。

僕は、var を使う、使わないにかかわらず、

と、new を try の外側に書きます。
hoge.YYY() を catchブロックで呼び出さない場合も同様の書き方にしています。

確かに、new Hoge()での例外がキャッチできないですが、
new Hoge()での例外をキャッチしたい場合は、その上位スコープなり上位メソッドでキャッチすれば
良いと思います。

以前、Microsoft Enterprise Library のソースを覗いてみた時も、
結構、このスタイルでtry-catchが書かれていた記憶があるので、
この書き方は、僕だけが主張する特別なコードではないと思います。

もちろん、try { } の中で、new する場合もありますが、その時には、そもそも catchで、
hogeにアクセスするコードは書きませんし、
そうなったら、自分のコードが何かおかしなことになっているぞ、と考えてしまいます。

C#の try ブロックのスコープがもうすこし広くても良いのでは、と思うこともありますが、
そういった仕様なので、その仕様のなかで、どう書くかを考えたときに、
上記のスタイルが自然なのかなと...

try-finally の時も new は、try の外側に出します。
まあ、大抵は、using使うので、書くことは少ないですが...
http://msdn.microsoft.com/ja-jp/library/yh598w02(v=VS.100).aspx読んでもらえれば、new を try-finallyの外に出す理由は分かってもらえると思います。

まあ、いろんな意見の人がいると思うので、あくまでも僕個人の意見ということで...


この記事へのコメント
> 確かに、new Hoge()での例外がキャッチできないですが、new Hoge()での例外をキャッチしたい場合は、その上位スコープなり上位メソッドでキャッチすれば良いと思います。

はい、上位スコープでcatchすればいい場合は、もちろんそうです。

しかし、例えばStreamReaderでファイルオープンをして、オープンに失敗したときはログファイルにそれを記録しないといけないような場合はどうでしょう?

var sr=new StreamReader(path);を直接その場でcatchしてその場でログファイルに書き出すほうが合理的です。(必要なら例外は再throwします)

これを上位スコープ(だけ)でcatchすると上位スコープで都度ログに書き出すコードが必要になります。

まあ、そんなわけでvarでassignするときにその場で例外をcatchしたいケースもあって、今回の問題はそんなケースについての記事でした。
Posted by やねうらお at 2010年09月30日 05:58
>上位スコープ(だけ)でcatchすると上位スコープで都度ログに書き出すコードが必要
素人考えですけど、ログの機能は分離して
ログ付きクラスみたいなラップにしたらいいんじゃないかな。
Posted by BLUEPIXY at 2010年09月30日 19:47
本文でも書きましたが、try { } の中で、new する場合もあります。
new の例外をキャッチしたい場合は、try { } の中で new します。これを否定するものではありません。

> StreamReaderでファイルオープンをして、オープンに失敗したときはログファイルにそれを記録しないといけないような場合はどうでしょう?

まさしく、これがその場合なわけですが、

try {
var sr = new StreamReader(path);
return sr;
} catch {
ログ出力とか.... ここで、st にアクセスすることはない。
throw;
}

などと書いて、スコープの問題が発生しないように書いています。
この中でリトライする場合には、もう少し複雑なコードになりますが、
その場合でも、スコープの問題は発生しないと思います。

その上位では

using (var st = new MyStream(...)) {
st.MyRead(...);
...
}

で、やはり、スコープの問題は発生しないかと思います。

どんな場合でも、var と try-catchの スコープの問題が出ないかと言われると自信がないですが...

ここでも、catchするべきという考えの人もいますが、
.NET では、むやみに例外をキャッチしないほうが良いと思っています。
集約例外ハンドラとか、最上位メソッドなどで、例外を処理するようにすれば、いいのではと思います。

Posted by Gushwell at 2010年09月30日 21:25
 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52074323
この記事へのトラックバック
素敵なエントリーの登録ありがとうございます - .NET Clipsからのトラックバック
try-catchのスタイル【.NET Clips】at 2010年09月30日 00:13