掲示板お問い合わせランダムジャンプ



この広告は30日以上更新がないブログに表示されております。 新しい記事を書くことで広告を消すことができます。

Top Index

2014年07月26日
例外処理入門(その1)
VB.NETではTry〜Catch文を使用して簡単に例外処理が書けますが、
使いこなすにはとても奥が深いものとなっています。
そこで、例外処理の勘所をメモしておきます。

Throw文で例外を起こそう


例外処理を学ぶためには、まず意図的に例外を起こす方法を覚えましょう。
意図的に起こすことで、例外とどのように付き合えばよいかが見えてきます。



Throw New Exception("エラーメッセージ")

と記述すればそこでプログラムがエラーで停止します。

ここでポイント

・例外処理をせずに例外が発生するとプログラムは問答無用で止まります。
・VisualStudio上でデバッグ中に例外が起きた場合は、場所(クラス、行)、理由(例外名)がわかりますが、
 EXEにしたあとでは「<アプリケーション名>は動作を停止しました」と出るだけでノーヒントです。


EXEにしてもどんなエラーが出たのかがわかるように修正しましょう。

Try〜Catch文で例外を捕まえよう



Try〜Catch文を使うことで例外を捕まえること(例外の検知と復帰処理)ができます。
Try...Catch...Finally ステートメント (Visual Basic)[MSDN]

構文はMSDNなどの外部サイトに任せるとして、ポイントは
・Tryブロック内で例外が発生した場合、Catchブロックに飛ぶ
・Catchブロック内で例外処理を書く

です。
説明を若干端折っていますが、いきなり詰め込んでも仕方ないので現時点ではこの理解で構いません。
では先程のコードをTry〜Catch文を使って、エラーが出たらエラーメッセージを出すように改造しましょう。


メッセージボックスにエラーが出るようになりました。


Catchする例外を絞ろう(前編)


先程のコードは

Catch ex As Exception

と記述しているため、例外をすべて捕まえてしまいます。
正確にいうと、「Exceptionクラスを継承した例外はすべて捕まえてしまいます」

特段このままでも問題なさそうですが、なんでもかんでも捕まえればいいというわけではなく、
処理続行不能な例外(たとえば、オーバーフローとか)など捕まえることを推奨しない例外も存在します。

では、捕まえたい例外だけを捕まえるにはどうしたらいいでしょうか?
これを実現するには

Catch ex As 捕まえたいExceptionクラス

このように書きます。

とはいうものの、このままでは
1. 任意の例外は「Throw New Exception」で起こせといった
2. 例外を捕まえるにはTry〜Catch文で、「Catch ex As 捕まえたいExceptionクラス」で書けといった
3. 「1」でExceptionクラスで例外起こしているから、「2」で捕まえるなら「Catch ex As Exception」と書くしかないじゃないか!
と矛盾に満ちています。

そこで、「1」の「Throw New Exception」というコードを見直しし、
独自の例外クラスを作って、「Throw New カスタムException」とし、
「2」では「Catch ex As カスタムException」と書くことで解決させるとします。
では、「カスタム例外クラス」を作るところから行きましょう。


カスタム例外を作ろう


MSにガイドラインがありますので、紹介しておきます。

カスタム例外のガイドライン[MSDN]

・System.Exception または他の一般的な基本例外のいずれかから例外を派生させます。ただし、ApplicationExceptionを継承することは推奨されていません。
・例外クラス名の終わりには、"Exception" というサフィックスを付けます。
・例外をシリアル化可能にします。
・すべての例外に対して、少なくとも、次の共通コンストラクターを提供します。

Public Sub New()
Public Sub New(ByVal message As String)
Public Sub New(ByVal message As String, ByVal inner As Exception)
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)


なぜ、「ApplicationExceptionを継承することは推奨しない」とわざわざ断り書きがあるのでしょう?
実はこういういきさつがありました。
本来、カスタム例外は ApplicationException クラスから派生しなければならないと考えられていましたが、実際には、それによって大きな価値が付加されたことはないようです。

では、なぜ「価値がない」のか?
推測ですが重要なのは「Catchで捕まえた例外をどう処理するか」であり、
「ユーザが独自に作った」というグルーピングに意味があまりなかったからだと思われます。

そこで「Catchで捕まえた例外をどうするか」という視点で具体的に例外クラスを記述してみましょう。


ソースコードのコメントにもありますが、「軽微な例外」として定義しました。
使い方はこのようなものを想定しています。

Throw New MinorException("名前は必須です")
Throw New MinorException("ユーザによって処理が中止されました")

どれもシステムを停止させるような例外ではありませんよね?
つまり、CatchブロックでMinorExceptionをフックした場合、「エラーメッセージ処理をして処理を抜けていい(プログラムを停止させなくてもよい)」ということになります。


Catchする例外を絞ろう(中編)


前段にてカスタム例外クラスができましたので、例外発生処理、Try〜Catch文を書き直しましょう。

これでガイドラインに沿った例外実装となります。


Catchする例外を絞ろう(後編)(任意)


ガイドラインでは以下の例外クラスを発生させることを推奨しています。
標準の例外の種類のキャッチとスロー[MSDN]

・InvalidOperationException
不適切な状態では、System.InvalidOperationException 例外をスローしてください。
オブジェクトの現在の状態から判断して、プロパティ セットやメソッド呼び出しが不適切な場合は、System.InvalidOperationException をスローする必要があります。
たとえば、読み込み用として開かれている System.IO.FileStream に書き込みが行われた場合は、System.InvalidOperationException 例外をスローしてください。

・ArgumentException、ArgumentNullException、および ArgumentOutOfRangeException
適切な引数がメンバーに渡された場合は、System.ArgumentException またはそのサブタイプのいずれかをスローしてください。

現在のコードではカスタム例外である「MinorException」以外の例外は検知対象ではありませんので、
仮に「ArgumentException」が発生した場合はプログラムが止まります。
というわけで、これらの例外も検知できるように改造してみましょう。


※今回は複数の例外をCacthする例として上記のようなコードを書きましたが、
Catchしても例外処理する必要がない場合は、そもそもこの(Catch ex As InvalidOperationException)コードはいりません。


必ず処理されるFinallyブロックを書こう(任意)


いままで説明してきませんでしたが、Try〜Catch文にはFinallyブロックという「正常に動作しようが、例外が発生しようが必ず通るコード」を書く場所があります。
具体的なシチュエーションはこんな感じ。

・データベースを使用した処理では、最後にコネクションを切断しなければならない
・テンポラリファイルを使用した処理では、最後にテンポラリファイルを消さなければならない
(※1)

今回はサンプルではこのような処理は必要ありませんが、構文の例として書き足しておきます。



※1 IDisposeインターフェイスで実装する方法もありますが、ここで説明するとややこしくなるので省略。
[ 投稿者:mk3008 at 09:00 | VB.NET | コメント(0) | トラックバック(1) ]

この記事へのコメント

この記事へのトラックバック
例外処理入門(その2)
例外処理入門(その1)の続き。例外の再発生(その1)「例外発生時の事後処理を書き、エラー処理は呼び出し元に任せる」ということはよくあります。...
投稿者: VB.NETで作る! at 2014-07-27 11:07:59

この記事へのトラックバックURL
http://shinshu.fm/MHz/88.44/a02480/0000446206.trackback

この記事の固定URL
http://shinshu.fm/MHz/88.44/archives/0000446206.html

記事へのコメント
 
簡単演算認証: 7 x 9 + 5 =
計算の答えを半角英数字で入力して下さい。
名前: [必須]
URL/Email:
タイトル:
コメント:
※記事・コメントなどの削除要請はこちら