C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

using のインスタンス生成で例外が発生する場合の処理 /dogatana (19/01/05(Sat) 12:25) #89819
Re[1]: using のインスタンス生成で例外が発生する場合の処理 /WebSurfer (19/01/05(Sat) 13:55) #89820
  └ Re[2]: using のインスタンス生成で例外が発生する場合の処理 /dogatana (19/01/06(Sun) 11:00) #89825 解決済み


親記事 / ▼[ 89820 ]
■89819 / 親階層)  using のインスタンス生成で例外が発生する場合の処理
□投稿者/ dogatana (1回)-(2019/01/05(Sat) 12:25:02)

分類:[C#] 

こんにちは。

CSVファイルを書き込む処理を実装しています。

よくあるように、using を利用しているのですが、該当ファイルが既にExcel開かれていると
StreamWriter のインスタンス生成で例外が発生します。
この例外の処理のため using ブロックを try - catch で囲んだのですが、try - catch は
比較的限定された範囲で使用するのが通例と聞いており、このように usingブロックを囲むと
範囲が広すぎるように思え、気持ち悪さがあります。

この例のように、using のインスタンス生成で例外が発生する場合は、using を使わず
try - catch - finally で実装するのが自然でしょうか。

ご教示いただければ幸いです。

static public string ExportCsv(string filename, IEnumerable<EventLog> list)
{
    try {
        var encoding = Encoding.GetEncoding("Shift_JIS");
        using (var sw = new StreamWriter(filename, false, encoding)) {
            sw.WriteLine(EventLog.Title);
            foreach (var item in list) {
                sw.WriteLine(item.ToCsv());
            }
        }
        return "";
    }
    catch (Exception e) {
        return e.Message;
    }
}

[ □ Tree ] 返信 編集キー/

▲[ 89819 ] / ▼[ 89825 ]
■89820 / 1階層)  Re[1]: using のインスタンス生成で例外が発生する場合の処理
□投稿者/ WebSurfer (1719回)-(2019/01/05(Sat) 13:55:35)
No89819 (dogatana さん) に返信

以下の記事によると、

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

***Quote***
try-catch 命令を書く場合には、業務エラーなどに変換したくない例外を、間違って捕捉しないよう
にしなければなりません。具体的には、以下のようなコードは絶対に書いてはいけません。

・複数行のコードをまとめて try-catch で囲む。
・一般例外(Exception クラス)を catch する。
・catch したあと何もしない。
***Unquote***

・・・ということですので、それに従えば質問者さんが書いたコードは「絶対に書いてはいけません」
という例になってしまいます。

どうすべきかは紹介した記事に書いてありますので興味があれば読んでみてください。

Part. 2 も紹介しておきます。

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



紹介した記事に書いてあることをまとめると、以下の通りになると思っています。

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

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

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

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

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

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

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

破損状態例外を処理する
https://msdn.microsoft.com/ja-jp/magazine/dd419661.aspx
[ 親 89819 / □ Tree ] 返信 編集キー/

▲[ 89820 ] / 返信無し
■89825 / 2階層)  Re[2]: using のインスタンス生成で例外が発生する場合の処理
□投稿者/ dogatana (2回)-(2019/01/06(Sun) 11:00:27)
2019/01/06(Sun) 11:06:59 編集(投稿者)

No89820 (WebSurfer さん) に返信

> 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/

情報ありがとうございます。

using (var ..) の形のままでは無理ですね。
いただいた内容も参考に、
1. try - catch で囲んだリソース生成
2. using でそのリソースを使用
のように、リソース生成と利用を分けることにしました。

ありがとうございました。


解決済み
[ 親 89819 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -