• ベストアンサー

【C#/Java?】try-catchでcatchせずにfinallyは一般的?

普段はJavaを使っているのですが、故あってC#のソースを簡易レビューすることになりました。 C#を始めてそれほど間もない人間の書いたソースなのですが、以下のようなソースをたびたびみかけます。 try {   // 処理 } finally {   // finally処理 } C#の場合、Javaとは異なり全ての例外はJavaで言うところの非チェック例外であると認識しています。(ただし、Javaの非チェック例外と同じ扱いをしていいとは思っていませんが……) 呼び出し元に起きうる全ての例外処理を任せるがfinally処理をしたいならば、このような書き方をするのが一般的なのでしょうか。 Javaの場合でもこのような書き方ができることは確認しましたが、Javaの場合は非チェック例外が起きる=バグであることがほとんどなので、このような書き方をする場面はあまりないように思います。 (もちろんチェック例外もthrowsを書けば同じように書くこともできるとは思いますが、自分ならやらないですし、そのようなソースを見たこともないです) ですので、単に自分がJavaを普段使っているからcatchがないことに違和感を感じるだけなのであれば、この問題はスルーしたいと思います。 C#経験者が周りにいない状況ですので、皆様のお知恵をおかりしたいと思います。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • SN1701
  • ベストアンサー率76% (16/21)
回答No.2

Javaの場合ですが、わたしは、よくこの書き方をします。 チェック例外でも、非チェック例外でも、例外処理を呼び出し元に任せるような設計にすることはあると思います。 呼び出された方では、例外の処理方法が決められないようなケースではcatchしないし、その場で処理すべき例外ならcatchするようにします。 例外をcatchするべきかということと、finallyで何らかの回復処理をしなければならないこととは、そもそも別の話なので、finally節だけになることがあるのは、自然なことだと思います。 finallyだけということは、finallyですべきことはあるが、そこでは例外をcatchすべきでないからcatchが無いと考えた方がいいでしょう。 逆に用もないのにcatchするのはよくないです。

TearsNight
質問者

お礼

回答、ありがとうございます。 よくよく考えてみれば、本当に仰る通りですね。 どうも自分がこれまで「try-catch、もしくはtry-catch-finally」と頑なに考えていた部分があるように思います。 これまで作ってきたものが、「起こった例外を別の例外でラップしてthrowする」という設計であったのも、 この考え方を固めてしまった原因のように思います。 catchしたものをそのままthrowするだけなら、throwsを書いてcatchしなければいいわけですよね。 どちらにせよ、例外処理は設計時の重要な項目ですから、この機会に深く掘り下げておこうと思います。

その他の回答 (1)

  • equinox2
  • ベストアンサー率48% (321/660)
回答No.1

>呼び出し元に起きうる全ての例外処理を任せるがfinally処理をしたいならば、このような書き方をするのが一般的なのでしょうか。 この方法でエラー発生の際の処理が全て記述できるなら、この方法が 一番シンプルだと思います。 以下の2008/12と2009/1に同様な内容の記述があります。 http://blogs.msdn.com/nakama/ ただ、物事には例外があって、業務エラーに類する物については、 呼び出し元に戻してしまえば良いとは一律には決められないので、 エラーの種類によっては、その場で catch する必要のある場合も 存在します。 (例)・ユーザ入力によるDBキー重複 → 知らせて再入力を促す    ・DBのロックタイプアウト →必要に応じてリトライ 私は、以前は以下の判断基準でエラー処理を統一させていました。 (1)想定できるエラー(業務エラーに多い)はその場でエラー処理 (2)想定できないエラーは呼び出し元に渡す(catchしない or Throw) (1)のケースを限定して適用し、それ以外は Catch しない というのが 実用的かも知れません。

TearsNight
質問者

お礼

回答ありがとうございます。 リンク先のブログ、非常に興味深く読んでいます。(現在進行形) 量も量ですし、かなり重要なポイントだと思うので、じっくり理解したいと思います。 Javaを普段扱ってる人間から見るとちょっと違和感のある記述でも、 equinox2さんのような意見やリンク先のブログなどを見ると「なるほど」と思いますね。 是非他の方の意見も聞いてみたいので、もうしばらく意見を募集してみたいと思います。

関連するQ&A

  • finally ってどのようなときにつかうんですか?

    処理A try 処理B catch 処理C finally 処理D ---------------------- 処理A try 処理B catch 処理C 処理D ---------------------- 以上2種類 どのみち 処理Dはとおりますよね? いったいどのような場合使うのでしょうか? 言葉で書くのが難しいのならソースでも構いません・・。 (言語はできたら VBかC#)

  • try~catch

    php初心者です try~catchをわかりやすく教えてください throw new Exceptionが出現したら、catchまでの処理をしないでとばすとゆうことですか? try~catchを抜けたら、他の処理は普通に実行されるのでしょうか? try~catchのカッコ{で囲む範囲は大きくしたほうがいいでしょうか?(大きく囲むと処理スピードおそくなりますか?) try { throw new Exception('エラーが発生しました');  print "hoge"; } catch (Exception $e) {  echo '例外発生', $e->getMessage(), "\n"; }  print "foo"; よろしくお願いします

    • ベストアンサー
    • PHP
  • C++のtryとcatch

    C++で、例外処理としてtryがあるのですが、どういった使い方をするのでしょうか? それと、catchも使い方がわかりません。 どなたか教えてください。 よろしくお願いします。

  • try catchについて

    try catchの動きで質問があります。 以下が簡略化したソースです。 -------ここから--------------------- ストリーム1; ストリーム2; try{ try{ //ストリーム1を使った処理 }catch(IOException e){ throw e; }finally{ //ストリーム1のクローズ } try{ //ストリーム2を使った処理 }finally{ //ストリーム2のクローズ } } catch(IOException e){ throw new hogeException(); } ------ここまで-------------------------- 内側でスローされた例外は、外側でcatchされるのですか? また、内側でcatchをしなかった場合、外側でcatchされるのですか? この2点を教えていただきたいです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • try catch finally は必要か???

    smtpでメールを同期送信しております もちろん通常とおり前後をtry catch finally で囲んでおります 送信に時間が掛るので、今回非同期送信に改めました それに伴いイベントハンドラーも追加しました するとエラーが発生してもcatchには来ずイベントハンドラーのエラー発生の判定部分に来ます 質問? イベントハンドラーを設置した場合、try catch finallyは取り外しても良いのでしょうか?

  • Try~Catch、Finallyについて。

    下記のように、DataSetをXML出力するメソッドを作りました。 Public Sub WriteXml(ByVal xmlDs As DataSet) Try Dim fileStream As New System.IO.FileStream(holdFilePath, System.IO.FileMode.Create) Dim setting As New System.Xml.XmlWriterSettings '文字コード設定 With setting .Encoding = System.Text.Encoding.UTF8 .Indent = True End With Dim writer As System.Xml.XmlWriter = Xml.XmlWriter.Create(fileStream, setting) 'XMLへの書き込みを行い、FileStreamを閉じる xmlDs.WriteXml(writer) writer.Close() fileStream.Close() Catch ex As Exception MsgBox(ex.message) End Try End Sub メソッドは以上です。 writer.Close()、fileStream.Close()については、確実に 処理を行いたいので、Finallyで行おうかと思ったのですが、 その場合、Dim fileStream~、Dim writer~はTryの外に出さないと、 宣言されていないと言われてしまいます。 そうなると今度は、NewやXml.XmlWriter.Create(fileStream, setting) でコケた場合にCatchが出来ません…。 Usingを使うのが近いかなと思ったんですが、複数Newしている場合 でも使えるのでしょうか? 確実にClose処理を行うための改修箇所、アドバイスいただけ ないでしょうか? よろしくお願いします。

  • try~catchの使用方法

    プログラミング超初心者です。 現在、C++やjavaの勉強をしているのですが、 ・try~catchとはなんぞや ・どんな処理をするときにtry~catchをつけなければいけないのか がよくわかっていないので、教えていただけないでしょうか? また、そういったことが載っているサイトも併せて教えていただければうれしいです。

  • C# 例外が発生しないことの保障

    Javaと比較して書きます。 Javaで記述した場合: public class JavaClass {  public static SampleClass s = new SampleClass(); } C#で記述した場合: public class CSharpClass {  public static SampleClass s = new SampleClass(); } JavaでもC#でも、同じコードを記述しているように見えますが、Javaではnew SampleClass()コンストラクタで例外が発生しない事が分かっているのに対して、C#の場合では例外が発生しないとは言い切れません。 これは、Javaでは、例外をスローする可能性のあるメソッド宣言では、その全てについてthrows宣言をしなければいけないのに対して、C#にはこの制約が存在しないことが原因です。 これについて何が困るかといいますと、C#で、static宣言な変数や静的コンストラクタで安易にメソッド呼び出し等を行うと、キャッチできなくなってしまいます。 public class Exceptionner {  public Exceptionner()  {   throw new ApplicationException("Exceptionnerクラスの例外");  } } public class SampleClass {  public static Exceptionner e = new Exceptionner(); // ここで例外が発生するが、キャッチできない。 } public class MyEntryPoint {  public static void Main()  {   try   {    SampleClass s = new SampleClass();   }   catch (Exception e)   {    // System.ApplicationExceptionでなくSystem.TypeInitializationExceptionとなる。    // つまり、元の例外の情報は失われている    Console.WriteLine(e.GetType());   }  } } これを現在漠然と問題視していますが、何かよい解決策はありませんでしょうか。 望んでいる解決策: ・C#でもメソッドが例外を返さないという保障がソースレベルでメソッドやコンストラクタに宣言可能? ・C#では例外をちゃんとキャッチしなくてもスマートに記述することが可能? ・問題視する必要がない?(whyも含めて)

  • Javaの例外処理の書き方について

    Javaの例外はErrorとRuntimeExceptionは書かなくてもいいが、 Exceptionはtryでcatchする必要があると聞きました。 しかし、java.langのStringを使っても例外処理は書きません。 なぜ、例外を書くやつと書かないやつがあるのですか? たとえば、java.langを使うとしたら、 ClassNotFoundException CloneNotSupportedException Exception の3つをjava.langを使うメソッドのブロックの上にtry文が必要だと思うのですが。

    • ベストアンサー
    • Java
  • JAVAのExceptionについて(エラーハンドリング)

    JAVAの例外の取り扱いについて お世話になります。JAVAでWebアプリケーションを開発しているものです。エラーハンドリングについて、悩んでいます。 私は、我流でプログラムの開発を行ってきたため、エラーハンドリングについて、あまり知識がありません。 今回とあるプロジェクトのリーダーを任されることになり開発を進めていたのですが、気がついたらメンバーのプログラムにtry,catch,throwsなどのエラーハンドリングがコーディングされていない状態で困っています。(みんな外国人で私が今まで一から教えていました。) そこで、皆様はどのようにJAVAで例外を扱っているのかをお伺いしたいと思い投稿いたしました。 私の少ない認識では、 (1)最上位のクラス、画面に一番近いクラスでtry,catchを行う (2)Exceptionはすべてのクラスの例外をcatchするが、一つ一つのエラーを明確に定義する方がよい(何のエラーが発生したのかわからない為) ⇒ただし、ここが一番の悩みどころです。エラーを設定する考え方として、配列を扱っている場合は、ArrayIndexとか、ファイルを扱っている場合はI/OExceptionとかソースコードを見て判断すべきでしょうか? (3)独自エラークラスを作る場合は、Exception,RunnableExceptionを敬称する。 ⇒そもそも何故、独自Exceptionクラスを作る必要があるのでしょうか?画面によってメッセージ、処理、遷移先を変えたいから? 上記が私の持っている知識と、疑問点です。 正直自分自身がよくわかっていないため、他の外国人メンバーに説明できません。とりあえず、Exceptionをthrowするように言っているのですが、このままじゃまずいと思い投稿しました。 どなたか忌憚のないご意見をお聞かせください。

    • ベストアンサー
    • Java