none
システムエラーについて RRS feed

  • 質問

  • いつもお世話になっております。

    システムエラーをどこまで気にしてプログラミングを行えばよいのかわかりません。

    C#でプログラミングを行っているのですが、
    例えば変数の宣言や変数の代入でもエラー(例外)が起こりうるのでしょうか。
    または起こることを気にしてプログラミングする必要があるのでしょうか。

    みなさんはどのような例外処理を書いているのかというのを理由をつけて教えていただけないでしょうか。
    例えばtry…catchはどこで囲むのかとか、囲まなかったところは例外は起きないかとか、
    Application.ThreadExceptionを使うだとかです。
    場合によって違うかもしれないので、理由さえ書いていただければ個人的なコーディング基準で構いません。
    業務エラーではなく、システムエラーについてお願いします。

    コンソールアプリケーション(バッチ)とWindowsアプリケーション、Webアプリケーションで
    違うのであれば、それも教えていただけるとありがたいです。

    一般的にプログラムのこういうところではエラーは起こらないとかいう話が、私は分かっていないんだと思います。


    以下、私の現在の例外処理の書き方で書いたサンプルコードがあります。コンソールアプリケーションです。
    ちょっと長くかつメソッドに分割してないので読みにくいですが、添削をしていただけないでしょうか。
    サンプルなので意味のないコードが入ってますが、あくまで例外処理について知りたいため、そこを中心に指摘していただけますでしょうか。
    1 static void Main(string[] args)  
    2 {  
    3 //AppDomain.CurrentDomain.UnhandledExceptionは、実行後にダイヤログが出て止まるため、  
    4 //私は使用しません。  
    5   //どこで例外が発生するか(私が)わかっていないので、  
    6   //またバッチなので例外スローしっぱなしで処理が止まったままは困るので、全部tryで囲みます。  
    7   try 
    8   {  
    9     //変数の宣言も囲む必要があるのでしょうか?  
    10     int x,y,z;  
    11     double d;  
    12     string conStr, selectStr;  
    13     DataSet ds;  
    14     SqlConnection sqlCon;  
    15     SqlDataAdapter sqlDA;  
    16     SqlCommandBuilder sqlCB;  
    17     SqlTransaction transaction;  
    18       
    19     conStr = "接続文字列-省略" 
    20     selectStr = "SELECT * FROM testtable WHERE COLUMN1 = 'target'";  
    21  
    22     //インスタンス生成も囲む必要があるのでしょうか。  
    23     ds = new DataSet();  
    24     sqlCon = new SqlConnection(conStr);  
    25     sqlDA = new SqlDataAdapter(selectStr, sqlCon);  
    26     sqlCB = new SqlCommandBuilder(sqlDA);  
    27  
    28     //以下も囲むべきでしょうか。  
    29     x = 1;  
    30     y = 1;  
    31     z = x - y;  
    32     d = 1 / (double) z;  
    33  
    34     //もし一番外側で囲ってなかったら以下はtry…catchで囲むべきでしょうか。  
    35     Console.WriteLine("整数を入力してください");  
    36  
    37     if(int.TryParse(Console.ReadLine(), out z))  
    38     {  
    39       //入力値のチェックで例外は防げると思うので、ここではそれを記述。  
    40       if( z > 0 )  
    41       {  
    42         d = 1 / z;  
    43         Console.WriteLine("d = " + d.Tostring());  
    44       }  
    45       else 
    46       {  
    47         throw new Exception("0以下は入力しないで下さい。");  
    48       }  
    49     }  
    50     else 
    51     {  
    52       throw new Exception("入力値が不正です。");  
    53     }  
    54  
    55     //try…finallyでsqlconnectionを閉じるために記述  
    56     try 
    57     {  
    58       try 
    59       {  
    60         sqlCon.Open();  
    61       }  
    62       catch(Exception e)  
    63       {  
    64         throw new Exception("接続中にエラーが発生しました。" + e.Message);  
    65       }  
    66         
    67       transaction = sqlCon.BeginTransaction(IsolationLevel.ReadCommitted);  
    68       sqlDA.SelectCommand.Transaction = transaction;  
    69  
    70       //DB操作では例外が起こる可能性があるため囲む  
    71       try 
    72       {  
    73         sqlDA.Fill(ds);  
    74       }  
    75       catch(Exception e)  
    76       {  
    77         throw new Exception("Fillでエラー発生" + e.Message);  
    78       }  
    79  
    80       for(int i = 0; i < ds.Tables[0].Rows.Count; i++)  
    81       {  
    82         ds.Tables[0].Rows[i][2] = "change";  
    83       }  
    84  
    85       //DB操作では例外が起こる可能性があるため囲む  
    86       try 
    87       {  
    88         sqlDA.Update(ds);  
    89       }  
    90       catch(Exception e)  
    91       {  
    92         transaction.Rollback();  
    93         throw new Exception("Updateに失敗しました。" + e.Message);  
    94       }  
    95     }  
    96     finally 
    97     {  
    98       sqlCon.Close();  
    99     }  
    100   }  
    101   catch(Exception e)  
    102   {  
    103     Console.WriteLine("例外が発生しました。" + Environment.NewLine + e.Message);  
    104   }  
    105 }  
    106  

    よろしくお願いします。
    2009年2月4日 10:30

回答

  •  おはようございます。!(^^)!ふ~です。

    Windowsフォームアプリを開発している時代では、他の人のソースを
    見ましても、エラー処理は最小限です。基本的には、予想出来ない
    OSエラーは、OSのエラー処理を優先させております。
    つまり、OSは必要があれば、ユーザープログラムを停止しても構わな
    いと暗黙の了解のもとに作成しておりました。

    C言語の時代、特にエラー処理に気を使うのは、マルチCPUマルチタスク
    処理で、共有部のメモリ、I/Oをアクセスする場合に、ロック、セマフォー
    を使用してタイミングを取るなど、エラー処理を含め設計する必要が有りました。

    今日のC#言語プログラムでのアプリケーションドメイン内処理では、
    クラスのエラー戻り値があれば、必要な所で対応する程度です。
    気楽に設計してます。

    それでも、他のアプリケーションドメインとの通信、他のプロセス、
    ネットワークを使用した分散処理などは、エラー処理も含めて少しは考えて
    います。幸いなことに、パソコン内でのマルチCPU対応は、考慮しなくても
    良いので助かります。

    無理やり、エラー処理をルール化すれば、他のスレッドと関係する箇所では
    注意が必要。相手がどうなっているのか確認が必要と言うことでしょうか。
    SQL、シリアル通信、USB、I/O、パイプ、メモリ操作が主なメンバーでしょう
    更に、最大、最小の限界値のチェックを忘れないようにしております。

    try -Catchに限れば、MSDNのクラスライブラリのリファレンスを眺めてエラー
    処理の指示があれば、考えております。面倒で、無視する場合も多いのですが
    連続運転したい場合は、丁寧に対応しております。

    2009年2月17日 1:52
  • 返信が遅くなりました。ごめんなさい。

    ハッシュドビーフさん の発言:

    で、リソース解放用のtry…finallyではcatchしないので、その中で例外が発生した場合、集約例外ハンドラで後処理されることになると思うのですが、とりあえずここは私の認識で間違っていないでしょうか?

    私もそのように認識しています。間違っていないと思います。

    ハッシュドビーフさん の発言:

    それで、集約例外ハンドラで処理したあと、Gab_kmさんの発言にもあるように、エラーのダイアログが出てしまいます。

    う~ん、こちらではそのようなエラーのダイアログが表示されません。 Environment.Exitを書かれていないのでしょうか?

    ハッシュドビーフさん の発言:

    後処理後に終了するため、Environment.Exit()で終了すると、リソース解放用のfinallyが実行されないということなのです。

    そうですね。確実にリソースを解放したい場合は、catch文を書いた方が良いように思います。でないと、finallyが実行されなくなってしまいます。もしくは、CurrentDomain_UnhandledExceptionにEnvironment.Exitを書かないかだと思います。しかしこれだと、アプリケーションで何の対策もしていないので本当に異常終了っぽくなってしまいますが・・・。

    ハッシュドビーフさん の発言:

    ひとまず、基本的には後処理は集約例外ハンドラで行い、catchは業務エラー制御等のために使うということは理解しました。

    いや、後処理を集約例外ハンドラに書くのは無理があるでしょう。全ソース上に存在するあらゆるリソースを解放するコードを書かなければならなくなります。となるとそれぞれのfinallyに書くべきだと思います。そうなるとCurrentDomain_UnhandledExceptionでEnvironment.Exitを使えないとなります。しかし、使わないと例外をキャッチできないので不自然な終わり方になってしまいます。これを避けるためにはやはりCurrentDomain_UnhandledExceptionでEnvironment.Exitを使わざるをえなくなります。となると、try~finallyだったところを、try~catch~finallyにしなければならなりません。なので、確実に後処理をしたい場合は、try~catch~finallyにしなければならないということになるんじゃないでしょうか? ただし、コンソールアプリケーションの場合だけです。Windows Formアプリケーションの場合は、try~finallyにし、CurrentDomain_UnhandledExceptionでApplication.Exitと書いてあげれば良いように思います。いかがでしょうか? いや、私もこの指針に確信を持っているわけではありませんが。(^^;


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年2月18日 7:20
    モデレータ
  •  ハッシュドビーフさんこんばんは
     私はC#ではWindowsアプリケーションのみ書いています。ボタンクリックなどのユーザ入力イベントは全体の例外をキャッチしています。データベースコマンド発行の部分については部分的に例外をキャッチしわかりやすいメッセージに変換した上で再スローしています。 データベースについては積極的にエンジンから返される例外を活用しています。
     ユーザ入力イベントについてはコマンドパターンを使っていて、コマンドオブジェクトの中でtry - catchしてそこを必ず通るようにしています。ですからいちいちイベントプロシージャ毎にtry - catchを書くようなことはしていません。
     この例外ハンドラでは、サイレント例外・ユーザへの注意・その他の例外に分け、サイレント例外では何もしません。ユーザへの注意では!アイコンでメッセージ表示、その他の例外は×でメッセージ表示しています。その他の例外は開発中にバグが原因で出ることが多いので修正します。ユーザへの注意は下位のルーチンでスローさせるものでリリース後も発生します。データベースの例外もそれにあたります。


    http://www.mahoroba.ne.jp/~mw_ken
    2009年2月18日 13:35

すべての返信

  •  とりあえず以下をご紹介しておきます。

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

    #現在、Part.4まであります。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年2月4日 13:59
    モデレータ
  • こんばんは。
    DB操作で捕捉しようとしている例外が気になりました。

    3か所のtry~catch句では、System.Exceptionで待ち受けています。
    ですが、DB操作で問題が起こることが多いと考えられるので、捕捉される例外にはSqlExceptionの存在も意識されます。
    とくに、エラー番号を表すSqlException.Numberは重要な情報なので、
      throw new Exception("何らかのエラーメッセージ" + e.Message);
    とすると、その情報が失われてしまう虞があるのではないでしょうか。
    2009年2月4日 15:02
  • trapemiyaさん

    いつもお世話になっております。
    とあるコンサルタントの…というサイト様ですね。
    たまに拝見させていただいています。とてもわかりやすく解説されていますよね。
    紹介してくださったところも一度拝見しており、そこで業務エラーとシステムエラーがあることを知りました。
    part2くらいまでしか読んでないので、全部読んでみようと思います。


    Gab_kmさん

    回答ありがとうございます。
    以前ちらっと他部署のコーディングを見たところ、おっしゃるとおりSqlExceptionで場合分けしていました。
    そうしたほうがよいのでしょうね。


    また、お二人に質問なのですが、tryで全文囲っているところはどうでしょうか。
    trapemiyaさんが紹介してくださったサイトを拝見しますと、
    AppDomain.CurrentDomain.UnhandledException(集約例外ハンドラ)を使えというようなことが書いてありますね。
    例外の通知をこのイベントで書くまではよいのですが、イベント後例外が補足されなかったような動作になり、
    プログラムをデバッグするとか終了するとか選択するダイヤログがでてきて止まってしまうのが困ります(終了してくれればいいんですが)。
    別のスレッドで質問させていただいた際に書いたのですが、このイベント中にEnvironment.Exit()を実行すると
    finallyが実行されないので、強制終了させるのもどうかと思いました。
    ですので、try…catchで全文囲うようなコーディングにしたのですが、集約例外ハンドラとどちらがよいでしょうか。
    バッチ以外の場合は、人が使ってると思いますので、ダイヤログがあとから出ても問題ないと思うのですが、
    バッチは自動で動かすことも多いと思います。
    2009年2月4日 15:48
  • ハッシュドビーフ さんの発言:

    紹介してくださったところも一度拝見しており、そこで業務エラーとシステムエラーがあることを知りました。
    part2くらいまでしか読んでないので、全部読んでみようと思います。


    既に読まれていたんですね。了解いたしました。part2まで読まれればとりあえず最低限はOKだと思います。(私が勝手に言っていいのか(^^:)

    ハッシュドビーフ さんの発言:

    AppDomain.CurrentDomain.UnhandledException(集約例外ハンドラ)を使えというようなことが書いてありますね。
    例外の通知をこのイベントで書くまではよいのですが、イベント後例外が補足されなかったような動作になり、
    プログラムをデバッグするとか終了するとか選択するダイヤログがでてきて止まってしまうのが困ります(終了してくれればいいんですが)。

    特にそのような形にはならないと思うのですが、

    AppDomain.CurrentDomain.UnhandledException += new   
    UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 

    は書かれていますか?

    ハッシュドビーフ さんの発言:

    別のスレッドで質問させていただいた際に書いたのですが、このイベント中にEnvironment.Exit()を実行すると
    finallyが実行されないので、強制終了させるのもどうかと思いました。
    ですので、try…catchで全文囲うようなコーディングにしたのですが、集約例外ハンドラとどちらがよいでしょうか。
    バッチ以外の場合は、人が使ってると思いますので、ダイヤログがあとから出ても問題ないと思うのですが、
    バッチは自動で動かすことも多いと思います。

    紹介先のページに書かれている内容に沿えば、集合例外ハンドラに対して基本的にfinallyを書いてはいけません。例外キャッチと後処理は違うものですので、それを混同して書いてはいけません。try...catchで囲むのは、1行のみか、もしくは複数行で良いのは確実に後処理をしたい場合(例としてはRollBack処理が載っていました。後処理なのでそのままthrowしているのも重要です)です。したがって、本来は集約例外ハンドラで処理すべきでしょう。

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年2月5日 5:07
    モデレータ
  •  
    ハッシュドビーフ の発言:

    また、お二人に質問なのですが、tryで全文囲っているところはどうでしょうか。
    trapemiyaさんが紹介してくださったサイトを拝見しますと、
    AppDomain.CurrentDomain.UnhandledException(集約例外ハンドラ)を使えというようなことが書いてありますね。
    例外の通知をこのイベントで書くまではよいのですが、イベント後例外が補足されなかったような動作になり、
    プログラムをデバッグするとか終了するとか選択するダイヤログがでてきて止まってしまうのが困ります(終了してくれればいいんですが)。

    基本的に例外は、例外的な状況で発生します。発生したということは、通常想定できないような、ごくまれで且つ継続不可能な状況だということです。そのため、たいていの場合は例外を補足せず、システムに任せます。

    しかし、例外を捕捉したい状況もあります。例えば、ログ ファイルを書き込む場合。ファイルを開こうとしたら、他のアプリケーションで閲覧中かもしれません。他のスレッドが書き込みをしている最中かもしれません。そのため、「使用中のため開けないという例外」が発生することが容易に予想されます。

    また、ご提示のコードだと、データベースを更新するときに例外が発生したということは、何らかのデータの不整合が発生したということであり、それは業務を継続不可能な状況のはずです。しかし、ロールバックすることでデータを元に戻し、ユーザーにデータを修正していただく、つまり業務の手順を回復可能な場所に戻してやり直すことで、業務の継続を可能にすることができます。

    一部の実行系では、「エラー」と「検査例外」のふたつに分かれています。.NET Framework の場合、「エラー」と「検査例外」に分けた場合の「検査例外」に相当するものがなく、「エラー」のみが「例外」として実装されています。上記のような状況は、「検査例外の検出」あるいは、「エラーから検査例外への読み替え」と言えるでしょう。


    発生する可能性がある例外は、たいていリファレンスに書いてあります。それらを狙い撃ちで捕捉するのが通例です。

    また、例外を再スローする場合は、単に throw; とだけ記述します。現在発生している例外が、情報をまったく損なわずに再スローされます。もし、何らかの都合でラップする場合は、InnerException プロパティに指定します。すなわち、93行目は単に throw; とするか、throw new AppricationException("適切なメッセージ", e); とします。


    Jitta@わんくま同盟
    2009年2月5日 14:19
  • こんばんは。

    ハッシュドビーフ の発言:

    プログラムをデバッグするとか終了するとか選択するダイヤログがでてきて止まってしまうのが困ります(終了してくれればいいんですが)。



    バッチ以外は~のくだりから判断して(よく見たらMain()がありますね)、コンソールアプリケーションとして考えます。
    私も実験してみましたが、確かに未処理例外を捕捉しているのに、エラーのダイアログが表示されてしまいますね。

    どぼん!さんの次のページ:
    捕捉されなかった例外がスローされたことを知る
    の下の方に、この件に関するリンク(英語)が貼られていました。
    これは仕様の動作かもしれません。

    # trapemiyaさんが紹介されたブログを読んでみましたが、感動したというか、すごく勉強になりました。
    # 私はダメな例を結構やってしまっていますねー(^_^;)

    2009年2月5日 15:51
  • みなさま返信遅くなって申し訳ありません。
    私の悪いところですm( __ __ )m

    trapemiyaさん

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

    trapemiya の発言:

    既に読まれていたんですね。了解いたしました。part2まで読まれればとりあえず最低限はOKだと思います。(私が勝手に言っていいのか(^^:)

    一応調べてわからなかったところだけ質問しているつもりですが、プロフェッショナルのコーディングをたくさん見たことがないので、これでいいのかわからないことが多いです…つД`)
    逆にデザインパターンをたくさん見れば、もしかしたら質問がなくなるのかもしれません。

    trapemiya の発言:

    紹介先のページに書かれている内容に沿えば、集合例外ハンドラに対して基本的にfinallyを書いてはいけません。例外キャッチと後処理は違うものですので、それを混同して書いてはいけません。

    紹介先のページのPart.2には

    • 外側の try ブロックは、リソース解放のためのもの。(try-finally、catch は書かず、大きく囲む)
    • 内側の try ブロックは、業務エラー制御のためのもの。(try-catch、1 行だけを小さく囲む)

    と書かれていますね。
    で、リソース解放用のtry…finallyではcatchしないので、その中で例外が発生した場合、集約例外ハンドラで後処理されることになると思うのですが、とりあえずここは私の認識で間違っていないでしょうか?

    それで、集約例外ハンドラで処理したあと、Gab_kmさんの発言にもあるように、エラーのダイアログが出てしまいます。
    後処理後に終了するため、Environment.Exit()で終了すると、リソース解放用のfinallyが実行されないということなのです。

    ひとまず、基本的には後処理は集約例外ハンドラで行い、catchは業務エラー制御等のために使うということは理解しました。


    Jittaさん

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

    Jitta の発言:

    発生する可能性がある例外は、たいていリファレンスに書いてあります。それらを狙い撃ちで捕捉するのが通例です。

    また、例外を再スローする場合は、単に throw; とだけ記述します。現在発生している例外が、情報をまったく損なわずに再スローされます。もし、何らかの都合でラップする場合は、InnerException プロパティに指定します。すなわち、93行目は単に throw; とするか、throw new AppricationException("適切なメッセージ", e); とします。

    基本的には狙い撃ちにするのですね。了解です!
    例外の再スローの仕方も参考になります。今まで間違っていました…。

    Jitta の発言:

    基本的に例外は、例外的な状況で発生します。発生したということは、通常想定できないような、ごくまれで且つ継続不可能な状況だということです。そのため、たいていの場合は例外を補足せず、システムに任せます。

    ここで悩んでいます。システムに任せるといっても、流石に集約例外ハンドラは使いますよね。
    WindowsアプリケーションやWebアプリケーションは、(たぶん)人が使っているので集約例外ハンドラを使わずデフォルトのエラーダイアログを出しても気づくので問題ないと思うのですが、バッチの場合はどうでしょうか。
    それで、集約例外ハンドラを使う方法で悩んでいます。

    一般的には狙い撃ちにした例外以外はまず起こらないものだということで、なにも記述しないのでしょうか?


    Gab_kmさん

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

    はい、コンソールアプリケーションです。
    Windowsアプリケーションではダイアログが出て止まらなかったので、集約例外ハンドラでいいかなと思いました。
    そもそも人が操作してるでしょうし。

    どぼん!さんのページもよく拝見させていただいてます!
    そして、そのページも読みました(≧∇≦)b 

    でも逆に、集約例外ハンドラでキャッチしたことになって続行されたら、バッチの場合はもしかしたら困ることになるかもしれませんね。
    なので個人的には、Environment.Exit()をするとfinallyが実行されないことが問題だと思っています。
    もしくは代替手段があればいいのですが…。



     

    2009年2月11日 8:44
  •  おはようございます。!(^^)!ふ~です。

    Windowsフォームアプリを開発している時代では、他の人のソースを
    見ましても、エラー処理は最小限です。基本的には、予想出来ない
    OSエラーは、OSのエラー処理を優先させております。
    つまり、OSは必要があれば、ユーザープログラムを停止しても構わな
    いと暗黙の了解のもとに作成しておりました。

    C言語の時代、特にエラー処理に気を使うのは、マルチCPUマルチタスク
    処理で、共有部のメモリ、I/Oをアクセスする場合に、ロック、セマフォー
    を使用してタイミングを取るなど、エラー処理を含め設計する必要が有りました。

    今日のC#言語プログラムでのアプリケーションドメイン内処理では、
    クラスのエラー戻り値があれば、必要な所で対応する程度です。
    気楽に設計してます。

    それでも、他のアプリケーションドメインとの通信、他のプロセス、
    ネットワークを使用した分散処理などは、エラー処理も含めて少しは考えて
    います。幸いなことに、パソコン内でのマルチCPU対応は、考慮しなくても
    良いので助かります。

    無理やり、エラー処理をルール化すれば、他のスレッドと関係する箇所では
    注意が必要。相手がどうなっているのか確認が必要と言うことでしょうか。
    SQL、シリアル通信、USB、I/O、パイプ、メモリ操作が主なメンバーでしょう
    更に、最大、最小の限界値のチェックを忘れないようにしております。

    try -Catchに限れば、MSDNのクラスライブラリのリファレンスを眺めてエラー
    処理の指示があれば、考えております。面倒で、無視する場合も多いのですが
    連続運転したい場合は、丁寧に対応しております。

    2009年2月17日 1:52
  • 返信が遅くなりました。ごめんなさい。

    ハッシュドビーフさん の発言:

    で、リソース解放用のtry…finallyではcatchしないので、その中で例外が発生した場合、集約例外ハンドラで後処理されることになると思うのですが、とりあえずここは私の認識で間違っていないでしょうか?

    私もそのように認識しています。間違っていないと思います。

    ハッシュドビーフさん の発言:

    それで、集約例外ハンドラで処理したあと、Gab_kmさんの発言にもあるように、エラーのダイアログが出てしまいます。

    う~ん、こちらではそのようなエラーのダイアログが表示されません。 Environment.Exitを書かれていないのでしょうか?

    ハッシュドビーフさん の発言:

    後処理後に終了するため、Environment.Exit()で終了すると、リソース解放用のfinallyが実行されないということなのです。

    そうですね。確実にリソースを解放したい場合は、catch文を書いた方が良いように思います。でないと、finallyが実行されなくなってしまいます。もしくは、CurrentDomain_UnhandledExceptionにEnvironment.Exitを書かないかだと思います。しかしこれだと、アプリケーションで何の対策もしていないので本当に異常終了っぽくなってしまいますが・・・。

    ハッシュドビーフさん の発言:

    ひとまず、基本的には後処理は集約例外ハンドラで行い、catchは業務エラー制御等のために使うということは理解しました。

    いや、後処理を集約例外ハンドラに書くのは無理があるでしょう。全ソース上に存在するあらゆるリソースを解放するコードを書かなければならなくなります。となるとそれぞれのfinallyに書くべきだと思います。そうなるとCurrentDomain_UnhandledExceptionでEnvironment.Exitを使えないとなります。しかし、使わないと例外をキャッチできないので不自然な終わり方になってしまいます。これを避けるためにはやはりCurrentDomain_UnhandledExceptionでEnvironment.Exitを使わざるをえなくなります。となると、try~finallyだったところを、try~catch~finallyにしなければならなりません。なので、確実に後処理をしたい場合は、try~catch~finallyにしなければならないということになるんじゃないでしょうか? ただし、コンソールアプリケーションの場合だけです。Windows Formアプリケーションの場合は、try~finallyにし、CurrentDomain_UnhandledExceptionでApplication.Exitと書いてあげれば良いように思います。いかがでしょうか? いや、私もこの指針に確信を持っているわけではありませんが。(^^;


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年2月18日 7:20
    モデレータ
  •  ハッシュドビーフさんこんばんは
     私はC#ではWindowsアプリケーションのみ書いています。ボタンクリックなどのユーザ入力イベントは全体の例外をキャッチしています。データベースコマンド発行の部分については部分的に例外をキャッチしわかりやすいメッセージに変換した上で再スローしています。 データベースについては積極的にエンジンから返される例外を活用しています。
     ユーザ入力イベントについてはコマンドパターンを使っていて、コマンドオブジェクトの中でtry - catchしてそこを必ず通るようにしています。ですからいちいちイベントプロシージャ毎にtry - catchを書くようなことはしていません。
     この例外ハンドラでは、サイレント例外・ユーザへの注意・その他の例外に分け、サイレント例外では何もしません。ユーザへの注意では!アイコンでメッセージ表示、その他の例外は×でメッセージ表示しています。その他の例外は開発中にバグが原因で出ることが多いので修正します。ユーザへの注意は下位のルーチンでスローさせるものでリリース後も発生します。データベースの例外もそれにあたります。


    http://www.mahoroba.ne.jp/~mw_ken
    2009年2月18日 13:35
  • またまた返信が遅くなってしまい申し訳ありません。
    少々忙しかったもので…。


    !(^^)!ふ~さん

    >無理やり、エラー処理をルール化すれば、他のスレッドと関係する箇所では
    >注意が必要。相手がどうなっているのか確認が必要と言うことでしょうか。

    おそらく。!(^^)!ふ~さんがおっしゃっている部分は何人かのチームで
    ある程度の規模のプログラム開発をする場合を言っているのですね!?

    今のところは大規模なプログラミングをすることはないのですが、
    今後関わることがあるかもしれませんので参考にさせていただきます。

    回答ありがとうございました!
    また質問させていただいた場合もよろしくお願いします。


    trapemiyaさん

    >う~ん、こちらではそのようなエラーのダイアログが表示されません。 Environment.Exitを書かれていないのでしょうか?

    そのとおりです。finallyが実行されないので、最初は書いていたんですが、書くのをやめました。

    >となると、try~finallyだったところを、try~catch~finallyにしなければならなりません。なので、確実に後処理をしたい場合>は、try~catch~finallyにしなければならないということになるんじゃないでしょうか? ただし、コンソールアプリケーションの>場合だけです。

    そうですね、コンソールアプリケーションの場合だけ、try-catch-finallyを使ったほうがよさそうです。
    Winodowsアプリケーションも簡単なものだけ作って実行してみたのですが、集約例外ハンドラで問題なさそうです。

    また、たぶんですが、きっと書き込みしてくださってるみなさまはWindowsアプリケーション(もしくはWebアプリ)を作っている
    人が多そうなので、Windowsアプリケーションを作る場合は、皆さまの意見に従えばいいのではないかと思っております。

    大変、大変返信遅くなって申し訳ありません。
    trapemiyaさんの回答は毎回とても参考になり助かっております。
    返信遅くなってしまうこともありますが、今後もお付き合いいただけるとありがたいです。
    回答ありがとうございました!


    三輪の牛さん

    はじめまして!
    回答ありがとうございます。

    Windowsアプリケーション作成時に参考にさせていただきたいと思います。

    今回のように返信が遅くなってしまうこともありますが、
    返信は必ずするように心がけております。
    今後ともよろしくお願いします!

    2009年3月1日 2:20