質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • C#

    7098questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

【C#】try~catchのcatch部分はどう実装すべきか

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 911

BluOxy

score 149

C#のtry~catch句を使った実装について

お世話になっております。
物凄く初歩的な質問です。

掲題の件の設計・思想についてわからない所があります。
プログラムの例外処理は大体以下のようにコードを書いております。

public void Hoge(){
    try
    {
        //処理X
    }
    catch(Exception ex)
    {
        Log(ex); //例外の内容をログ出力
    }
}

上記コードのメリットは処理Xにて問題発生時、

  • 例外が補足されるためプログラムは終了せず、運用に支障を来たしにくくなる
  • 全ての例外が補足されるため、ログ出力されたときに不具合の原因を特定しやすい

ことです。

しかし、デメリットも当然あると思っており

  • OutOfMemoryExeption等、本来開発側が想定していないエラーを補足してしまうため、
    例外発生後は意図しない処理が起きる可能性がある

ことは良くないな…と思っております。

理想としては

  • 想定しているエラー
  • 想定していないエラー

を実装する処理によって逐次対応(かつ楽に実装)できたら良いな…と思っております。

最適解はあるのでしょうか。
皆様はどのように例外処理を実装されていますか。

ご教授のほどよろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+5

最適解はあるのでしょうか。皆様はどのように例外処理を実装されていますか。

例外処置について、自分的に「最適解」と思うことを書きます。

(1) 予測可能で正しい業務フローに戻すことができる「業務エラー」(例:ユーザーの入力間違い)と、予測できないもしくは予測はできても何の対応もできない「例外」(例:DB サーバーダウン)を区別して対処。

(2) 「例外」はランタイムに拾わせてアプリケーションを停止させる。

(3) よほどのことがない限り try-catch は書かない。

(4) キャッチせざるを得ない場合でも Execption はキャッチしない。

(5) 間違って補足してしまった例外は throw する。(注:catch ブロックでキャッチした例外を throw するとスタックトレースが途切れるので単に throw と書く)

(6) ユーザーへの通知が必要なら、集約的例外処置を利用する。

詳しくは以下の記事を見てください。

NETの例外処理 Part.1
https://blogs.msdn.microsoft.com/nakama/2008/12/29/net-part-1/

.NETの例外処理 Part.2
https://blogs.msdn.microsoft.com/nakama/2009/01/02/net-part-2/

あと、.NET 4 からは破損状態例外は catch できなくなっているそうですが、「それでも Catch (Exception e) を使用するのはよくない」ということについては以下の記事を見てください。

破損状態例外を処理する
https://msdn.microsoft.com/ja-jp/magazine/dd419661.aspx

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 13:44

    ・意図した例外は対応する処置を施して業務処理に戻す
    ・意図しない例外はtry catchしない※任意で(6)を使う
    ・何処で例外が起きたか、例外の種類がわからなくなるためException exは使うべきではない
    辺りがとても参考になりました!!
    ありがとうございます。

    キャンセル

  • 2018/06/08 14:18

    > 何処で例外が起きたか、例外の種類がわからなくなるためException exは使うべきではない

    ログを取るためなどの理由で Exception ex をキャッチするのは有りだと思いますが、キャッチしっぱなしで例外をなかったことにしてしまうのはもちろん NG で、再 Throw すべきですが、その時 Throw ex とするとスタックトレースが途切れるので、単に Throw とすべきということを言ったつもりですが、そのあたりは理解していただけたでしょうか?

    キャンセル

  • 2018/06/08 14:28 編集

    > Throw ex とするとスタックトレースが途切れるので、単に Throw とすべき
    確認しました。

    常時稼働の必要があるプログラムの場合、インパクトの大きさは
    「落ちること>例外をなかったことにする」になってしまいますので
    ・意図した例外は対応した処置を行う
    ・意図しない例外はthrowして(2)を行う
    を意識した実装をしてみようと思います。

    キャンセル

+3

こんにちは。

想定できるエラーならば、普通にその想定に従って可能な対処を行う、もしくは、そもそもそのシナリオが発生しないように設計する方向ですね。

想定外のエラーはバグですので、経験的には誤動作するよりは落とした方が良いです。不具合はなるべく早期発見できるようにすると信頼性が上がります。
頻繁に落ちてユーザに強いストレスをかけないで済む程度に丁寧なテストを行うことは必須ですが、これは落とす落とさないに関係なくやるべきことです。むしろ、落とさないことで問題点を潜在させ、テストにパスしてしまうと悲惨ではないでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 12:38 編集

    テストでは想定できる想定できない関わらず何らかの例外がエラーログに出ていないこと、動作に問題がないことを確認することにより
    あらかじめ問題点がテスト時点ではないことを確認しています。

    テストにパスしてしまった上で起きてしまった例外も、
    まずは補足して、その上で継続していきたいと思っております。
    ※例えばNullReferenceExceptionやArgumentOutOfRangeException等の例外が発生したとき、
    それらの例外が実運用に支障を来たさない場合はとりあえず継続させたい意図があります。

    上記のような実装は不味いでしょうか?
    反対に言うとそういった例外も予め全て網羅するのが理想で、
    万が一実運用でプログラムが落ちてしまった場合は
    ごめんなさいして逐次追加する…と言った流れになるのでしょうか。

    個人的には、あらかじめ全例外を取っておいて
    致命的なエラーが起きた場合は逐次修正する…となってしまうのが実情なのかなと
    思っています。

    キャンセル

  • 2018/06/08 13:00

    > テストでは想定できる想定できない関わらず何らかの例外がエラーログに出ていないこと
    なるほど。ログを検索すれば可能ですね。であれば、テストでの見落としは発生しにくそうです。
    後は実運用中に発生した不具合をなるべく早期に捕まえるか、先延ばしするかの差ですね。
    実運用中もログチェックを時々行い、例外が発生していないことをチェックするのであれば、早期発見という意味では落とす必要はないように思います。

    後は想定外のエラーによる誤動作をどう考えるかの問題と思います。
    クライアントと良く話し合うしかないのでは?

    > ※例えばNullReferenceExceptionやArgumentOutOfRangeException等の例外が発生したとき、
    それが実運用に支障を来たさない場合はとりあえず継続させたい意図があります。

    実運用に支障を来さないことが判っているものであれば、それは想定内と思います。この場合は継続してよいと思いますよ。

    > それでも実運用でプログラムが落ちてしまった場合は
    ごめんなさいして逐次追加する…と言った流れになるのでしょうか。

    対象によると思います。
    誤動作した時の被害が大きく、落ちても被害が酷く出ない対象なら落とした方が良いと思います。
    誤動作しても大きな被害はです、むしろ動作継続して欲しい対象(あまりどんな対象か想像できないですが)ならば、継続した方が良いと思います。

    キャンセル

  • 2018/06/08 13:59

    回答ありがとうございます!!
    参考になりました。

    >動作継続して欲しい対象
    ざっくり言うとある物を監視するシステムで、
    万が一何らかの問題が発生した時の発見が遅れないよう基本的には常時稼働して欲しい対象となります。

    キャンセル

  • 2018/06/08 14:12

    なるほど!
    例えば、自動監視システムのようなオペレータが常駐しないようなものの場合、監視を継続することが重要ですし、誤動作と言っても最悪動作が止まるものでしょうから、止めるよりできるだけ継続した方が良さそうですね。なるほどです。

    キャンセル

0

想定している例外はその想定された対策を行います。
想定されてない例外は動作に影響を与えないように対策を行います。

はやいはなしが、テストを十分にしよう、ということしかないかと。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 14:01

    回答ありがとうございます!!

    > はやいはなしが、テストを十分にしよう、ということしかないかと。
    詰まる所、こうなりますよね。
    全網羅は難しいですが…

    キャンセル

  • 2018/06/08 14:16

    網羅は難しいですねえ。
    網羅したつもりでいても、思いもよらぬ所から、ってのが跡を絶ちません
    予期せぬ例外はほっとけ、というのも理解はできるけど、それが許されるかどうかはべつのはなし。

    キャンセル

0

例えば。

// 業務上の例外(システム起因以外)をこう定義する。
public class BusinessException : Exception {
}
try{
  // 業務処理
}catch(BusinessException e){
  // 業務上の例外なので業務用ログなどに出力する
}catch(Exception e){
  // システム上の例外なのでシステムログを出力し、処理を停止する
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 13:10 編集

    パッと見ですが、良さそうな思想ですね!!

    ちなみに、例外が発生した時の区別は.NETランタイム側でどう判断するのでしょうか。

    例えばNullReferenceExceptionが起き、その例外の根本原因が業務処理上の問題だった場合は、
    BusinessExceptionとして処理したいです。
    しかし、どのように検知の仕組みを作れば良いでしょうか。

    キャンセル

  • 2018/06/08 13:13

    > NullReferenceExceptionが起き、その例外の根本原因が業務処理上の問題

    ↑その箇所でNullReferenceExceptionをcatchして、BusinessExceptionを新たにthrowすればよいかと。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    エラーについて

    音楽ファイルを鳴らすためのプログラムを勉強しているのですが、 以下のように書いたところ、 「音楽プレイヤーの準備をします。」のerrorの箇所でエラーが出てしまいます。 どの

  • 解決済

    エラーの検知がうまくできない

    <form action="" method="post" id="signup2"> <p> メールア

  • 解決済

    (Java)throwとthrowsの違いについて

    Javaを勉強している者です。 タイトルの通り、Java言語の例外処理で使われるthrowとthrowsの違いが よく分かりません。 どのような場合にthrowを使い、どのよ

  • 解決済

    DBエラーにおいて接続失敗と未存在エラーを分けたい

    JavaのJPAを使用してWebアプリケーションを作成しています。 今、実装している仮会員テーブルの検索でDB検索結果が0件の場合に「ただのDbエラーではなくレコード未存在のエラー

  • 解決済

    try/catchの使い方

    try/catchの使い方なのですが。 下記はファイルをコピーペーストする関数になります。 処理が正常に行われたかを判断するためにtry/catchを使用したのですが、行数が倍

  • 受付中

    phpデータの受け渡しがうまくいかない

    データベースの情報を修正するフォームを作っていて、その時の画面がうまく動作しないのですがどこが間違っていて動作しないのかよくわかりません。どなたか教えていただけないでしょうか?

  • 解決済

    constへの代入行だけをtry-catchしたい(ES6+Babel)

     前提・実現したいこと ES6以上(Babelで変換可能な範囲内)で、「const変数にある関数の実行結果を代入」、そして「関数が例外を投げたら、実行中の関数からも抜ける」を実現し

  • 解決済

    Intentで遷移するActivityがない時に処理を弾く方法

    やりたいこと 遷移先のActivityが存在しない場合落ちるのを防ぎ、ログなどで表示をさせたいと考えています。 現状のコードと落ちた際のエラー AndroidでIntentを使

同じタグがついた質問を見る

  • C#

    7098questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。