連載
改訂版
|
|
|
本記事は、(株)技術評論社が発行する書籍『VB6プログラマーのための入門 Visual Basic .NET 独習講座』の一部分を許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。 |
構造化例外処理の確実な終了処理 |
これまでに、非構造化例外処理にあって構造化例外処理にはない機能があることは紹介したが、逆の事例もある。つまり、構造化例外処理にあって非構造化例外処理にはない機能も存在する。
まず、以下のVB 6のソースを見ていただきたい(リスト9-61)。
|
|
リスト9-61 複数の終了処理が必要となるプログラム |
これを実行するとリスト9-62のようになる。
|
|
リスト9-62 リスト9-61の実行結果 |
このソースには、2個のOpenステートメントと、3個のCloseステートメントがある。数が一致しないのは、6行目のOpenステートメントに対応するCloseステートメントが2個あるためで、ここではOn Error Gotoステートメントでエラー処理を行った場合と、正常終了を行った場合について、それぞれCloseステートメントが必要とされている。これはResumeステートメントを使って処理を戻す手法を使うことができず、1つのCloseステートメントでは済ませられない事例である。このような状況になると、うっかりCloseステートメントを忘れる場合があるので危険である。特に、処理の流れが複数に分かれたとき、どの流れでも確実にCloseステートメントを配置するように注意を払うのは大変であり、しばしば見落としが発生する。
このような問題をスマートに解決する方法が、VB.NETの構造化例外処理には用意されている。それを使った例をリスト9-63に示す。
|
|
リスト9-63 Finallyブロックを使用して終了処理を行うプログラム |
これを実行すると以下のようになる。
|
|
リスト9-64 リスト9-63の実行結果 |
このソースを見ると、FileOpen関数が2個で、FileClose関数が2個であることが分かる。つまり、数が一致している。このソースで注目すべき点は、15行目のFinallyブロックである。Finallyブロックは、Tryステートメントの後に、Catchブロックに続けて記述することができる。そして、Finallyキーワード以降に記述されたステートメントは、Tryステートメントから処理が抜け出すときに必ず実行される。つまり、正常終了でも例外発生でも、条件に関係なく、必ず最後に実行されることが保証されている。この場合、11行目の計算が正常に終了しても、DivideByZeroExceptionクラスの例外を発生させても、あるいは、ほかのいかなる例外が発生しても、このTryステートメントのブロックから抜け出すときには必ず実行されることが保証されている。
これにより、開いたファイルを確実に閉じる、といった処理を容易にわかりやすく記述することができる。これは、非構造化例外処理と比較して、構造化例外処理のほうが強力である理由の1つである。ファイルのクローズ忘れが確実に防止できるとしたら、それは非常にありがたいことではないだろうか?
なお、Finallyブロックがどのようなケースで実行されるかについては、次節で取り上げている。
Finallyブロックの確実性 |
構造化例外処理の確実な終了処理では、Tryステートメントで使用するFinallyブロックについて説明した。では、これはどの程度確実に動作するものなのだろうか。果たして、無条件に頼ってよいものなのだろうか? それを確認するために、さまざまなケースでFinallyブロックを使用するサンプル・プログラムを記述してみた(リスト9-65)。
|
|
リスト9-65 さまざまなケースでのFinallyブロックの動作を検証するプログラム |
これを実行すると以下のようになる。
|
|
リスト9-66 リスト9-65の実行結果 |
1〜7行目のコードは、いきなりメソッドから抜け出した場合である。実行結果を見ると、5行目が実行されることが分かる。
9〜17行目は繰り返しの途中から脱出する場合である。実行結果を見ると、14行目が実行されることが分かる。
19〜27行目は繰り返しの途中から脱出だが、Tryブロックがループの外側にある点が異なる。実行結果を見ると、25行目が実行されることが分かる。脱出する個所がTryブロックの中でありさえすれば、Tryブロックを記述する場所に関係なく、Finallyブロックが実行される。
29〜44行目はTryブロックが2重にネストしていて、どちらにもFinallyブロックが存在する場合である。実行結果を見ると、37行目も42行目も、両方とも実行されることが分かる。複数のTryブロックがネストして、複数のFinallyブロックが存在する場合、それらはすべて実行される。そのため、上位あるいは下位のTryブロックにすでにFinallyブロックが存在するかどうかを気にする必要はない。書けば実行される。
46〜58行目は、繰り返しがネストした途中から脱出する場合である。実行結果を見ると、56行目が実行されることが分かる。ネストの深さはFinallyブロックの実行とは関係ない。
60〜74行目は、繰り返しの途中から例外が発生した場合である。実行結果を見ると、70行目と72行目が実行されることが分かる。深いネスト状態から例外が起きても、Finallyブロックは確実に実行される。
76〜82行目は、何も問題なくTryブロックの実行を終える場合である。実行結果を見ると、80行目が実行されることが分かる。途中脱出や例外の発生がなくても、FinallyブロックはTryブロックから抜ける際に実行される。
深い階層からの例外とFinallyブロック |
Finallyブロックの確実性で、Finallyブロックがどのようなケースで実行されるかを示したが、ここではもう1つ別のサンプル・プログラムを記述してみた。ここでは、メソッド呼び出しを何重にも行っていて、その内部で例外を発生させている。
|
|
リスト9-67 深い階層で発生した例外に対するFinallyブロックの動作を検証するプログラム |
ここではtest1メソッドで例外が発生し、Form1_Loadメソッドでその例外をキャッチしている。そこでポイントになるのは、その中間に位置するtest2〜4メソッドに含まれるFinallyブロックである。例外をキャッチするTryブロックはForm1_Loadメソッド内にあるが、それではこの例外をキャッチしないTryブロックを持つ、test2〜4メソッドに含まれるFinallyブロックはどうなるのだろうか。
これを実行すると以下のようになる。
|
|
リスト9-68 リスト9-67の実行結果 |
結果を見て分かるとおり、すべてのFinallyブロックに続くコードが実行されている。Finallyブロックは、そのTryブロックでキャッチするか否かを問わず、すべて有効である。
『VB6プログラマーのための入門 Visual Basic .NET 独習講座』 本記事は、(株)技術評論社が発行する書籍『VB6 プログラマーのための 入門 Visual Basic .NET 独習講座』から許可を得て転載したものです。 【本連載と書籍の関係について 】 この書籍は、本フォーラムで連載した「連載 プロフェッショナルVB.NETプログラミング」を大幅に加筆修正し、発行されたものです。技術評論社、および著者である川俣晶氏のご好意により、書籍の内容を本フォーラムの連載記事として掲載させていただけることになりました。 →技術評論社の解説ページ ご注文はこちらから |
INDEX | ||
[連載] 改訂版 プロフェッショナルVB.NETプログラミング | ||
Chapter 09 例外処理 | ||
1.On Error Gotoを使用した非構造化例外処理/Try〜Catchを使用した構造化例外処理 | ||
2.構造化例外処理と非構造化例外処理の混用/On Error Resume Next/複数のエラーを扱う | ||
3.例外情報の活用/ネストした例外処理 | ||
4.例外の再発生/プログラムにより明示的に例外を発生させる | ||
5.例外の自作/InnerExceptionについて | ||
6.構造化例外処理の確実な終了処理/Finallyブロックの確実性/深い階層からの例外とFinallyブロック | ||
「改訂版 プロフェッショナルVB.NETプログラミング 」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|
- - PR -