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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

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

Q&A

解決済

4回答

13455閲覧

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

BluOxy

総合スコア2663

C#

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

0グッド

1クリップ

投稿2018/06/08 02:48

編集2018/06/08 03:03

######C#のtry~catch句を使った実装について
お世話になっております。
物凄く初歩的な質問です。

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

lang

1public void Hoge(){ 2 try 3 { 4 //処理X 5 } 6 catch(Exception ex) 7 { 8 Log(ex); //例外の内容をログ出力 9 } 10}

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

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

ことです。

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

  • OutOfMemoryExeption等、本来開発側が想定していないエラーを補足してしまうため、

例外発生後は意図しない処理が起きる可能性がある

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

理想としては

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

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

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

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

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

(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 04:02

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2018/06/08 04:44

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

退会済みユーザー

2018/06/08 05:18

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

2018/06/08 10:04 編集

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

0

こんにちは。

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

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

投稿2018/06/08 03:08

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2018/06/08 03:47 編集

テストでは想定できる想定できない関わらず何らかの例外がエラーログに出ていないこと、動作に問題がないことを確認することにより あらかじめ問題点がテスト時点ではないことを確認しています。 テストにパスしてしまった上で起きてしまった例外も、 まずは補足して、その上で継続していきたいと思っております。 ※例えばNullReferenceExceptionやArgumentOutOfRangeException等の例外が発生したとき、 それらの例外が実運用に支障を来たさない場合はとりあえず継続させたい意図があります。 上記のような実装は不味いでしょうか? 反対に言うとそういった例外も予め全て網羅するのが理想で、 万が一実運用でプログラムが落ちてしまった場合は ごめんなさいして逐次追加する…と言った流れになるのでしょうか。 個人的には、あらかじめ全例外を取っておいて 致命的なエラーが起きた場合は逐次修正する…となってしまうのが実情なのかなと 思っています。
Chironian

2018/06/08 04:00

> テストでは想定できる想定できない関わらず何らかの例外がエラーログに出ていないこと なるほど。ログを検索すれば可能ですね。であれば、テストでの見落としは発生しにくそうです。 後は実運用中に発生した不具合をなるべく早期に捕まえるか、先延ばしするかの差ですね。 実運用中もログチェックを時々行い、例外が発生していないことをチェックするのであれば、早期発見という意味では落とす必要はないように思います。 後は想定外のエラーによる誤動作をどう考えるかの問題と思います。 クライアントと良く話し合うしかないのでは? > ※例えばNullReferenceExceptionやArgumentOutOfRangeException等の例外が発生したとき、 それが実運用に支障を来たさない場合はとりあえず継続させたい意図があります。 実運用に支障を来さないことが判っているものであれば、それは想定内と思います。この場合は継続してよいと思いますよ。 > それでも実運用でプログラムが落ちてしまった場合は ごめんなさいして逐次追加する…と言った流れになるのでしょうか。 対象によると思います。 誤動作した時の被害が大きく、落ちても被害が酷く出ない対象なら落とした方が良いと思います。 誤動作しても大きな被害はです、むしろ動作継続して欲しい対象(あまりどんな対象か想像できないですが)ならば、継続した方が良いと思います。
BluOxy

2018/06/08 04:59

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

2018/06/08 05:12

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

0

例えば。

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

投稿2018/06/08 03:38

tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2018/06/08 04:12 編集

パッと見ですが、良さそうな思想ですね!! ちなみに、例外が発生した時の区別は.NETランタイム側でどう判断するのでしょうか。 例えばNullReferenceExceptionが起き、その例外の根本原因が業務処理上の問題だった場合は、 BusinessExceptionとして処理したいです。 しかし、どのように検知の仕組みを作れば良いでしょうか。
tkturbo

2018/06/08 04:13

> NullReferenceExceptionが起き、その例外の根本原因が業務処理上の問題 ↑その箇所でNullReferenceExceptionをcatchして、BusinessExceptionを新たにthrowすればよいかと。
guest

0

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

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

投稿2018/06/08 02:52

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2018/06/08 05:01

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

2018/06/08 05:16

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問