|
|
連載
改訂版 プロフェッショナルVB.NETプログラミング
Chapter 03 ステートメントの変化
株式会社ピーデー
川俣 晶
2004/03/17 |
|
ここでは、主にステートメントに関係するVB 6とVB.NETの相違点についてまとめてある。VB 6ではステートメントであったものが、VB.NETではクラス・ライブラリの機能に移行しているものもあるが、それらも取り上げている。ステートメントではないが、ファイル入出力ステートメントと関係するものとして、ファイルシステム・オブジェクトもここで扱っている。
VB 6ではWhileループの終わりにWendと記述するが、VB.NETではEnd Whileと記述する。実例は、古い制御構造On…GoToとOn…GoSubのサンプル・ソースで見ることができる。VB 6版のサンプル・ソース(リスト3-79)の29行目のWendが、VB.NET版(リスト3-81)の18行目のEnd Whileに変化していることが分かるだろう。
ほかの構造はすべて、End XXXというEndで始まる名前であるのに、Whileステートメントの終わりだけはEnd WhileではなくWendであった妙な不整合が解消された。IDEが勝手にWendをEnd Whileに直してくれるので、意識しなくても使えるかもしれないが、一応頭の片隅に入れておくとよいだろう。
VB 6で、プロシージャの実行を途中で打ち切るには、Exit Subステートメントなどを使用する。リスト3-1はそれを使用したサンプル・プログラムである。
1: Private Sub Form_Load()
2: Debug.Print "start"
3: Exit Sub
4: Debug.Print "end"
5: End Sub
|
|
リスト3-1 Exit Subステートメントを使用したプログラム
|
これを実行すると以下のようになる。
|
リスト3-2 リスト3-1の実行結果
|
見てのとおり、ソース3行目のExit Subステートメントで“Sub Form_Load()”の処理は中断され、4行目が実行されることはない。
これと同じ機能はVB.NETでも利用できる。リスト3-3はそれを示したサンプル・プログラムである。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Trace.WriteLine("start")
3: Exit Sub
4: Trace.WriteLine("end")
5: End Sub |
|
リスト3-3 リスト3-1をVB.NETで書き換えたプログラム
|
これを実行すると以下のようになる。
|
リスト3-4 リスト3-3の実行結果
|
さて、VB 6には、遠いむかしのご先祖様から継承したGosubステートメントとReturnステートメントというものがある。GoSubステートメントは、現在位置を保存してから指定ラベルに制御を移す。ReturnステートメントはGoSubステートメントが保存した位置に制御を戻す。これらは、同じコードを異なる場所から呼び出し可能にするサブルーチンというものを実現するために使用される。リスト3-5はVB 6でそれを利用した例である。
1: Private Sub Form_Load()
2: Debug.Print "start"
3: GoSub label
4: Exit Sub
5: Debug.Print "end"
6:
7: label:
8: Debug.Print "in subroutine"
9: Return
10:
11: End Sub
|
|
リスト3-5 GoSubステートメントとReturnステートメントを使用したプログラム
|
これを実行すると以下のようになる。
1: start
2: in subroutine |
|
リスト3-6 リスト3-5の実行結果
|
しかし、現在ではサブルーチンよりもはるかに強力な機能が多数揃っているので、めったに使われることのない機能と思われる。恐らく使われなくなってから10年以上は経過しているだろう。それを反映してか、VB.NETでは、GoSubステートメントは消滅し、Returnステートメントには別の任務が与えられるようになった。
以下は、それを使用した例である。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Trace.WriteLine("start")
3: Return
4: Trace.WriteLine("end")
5: End Sub |
|
リスト3-7 Returnステートメントのみを使用したプログラム
|
これを実行すると以下のようになる。
|
リスト3-8 リスト3-7の実行結果
|
この場合、Returnステートメントは、Exit Subと等価の働きをしている。これだけなら、ただ単に違う名前で同じ機能を記述できるだけである。しかし、Returnステートメントのもう1つの使い方は、単なる名前の違いではない。それについては、関数の戻り値とReturnステートメントで述べる。
VB 6では、値を返す関数(Function)を記述することができる。リスト3-9はそれを記述してみた例である。
1: Private Function test() As String
2: Debug.Print "start"
3: test = "Hello!"
4: Exit Function
5: Debug.Print "end"
6: End Function
7:
8: Private Sub Form_Load()
9: Debug.Print test()
10: End Sub |
|
リスト3-9 値を返す関数(Function)を記述したプログラム
|
これを実行すると以下のようになる。
|
リスト3-10 リスト3-9の実行結果
|
ここで把握していただきたいことは、以下の2点である。
- 関数の戻り値は、関数名への代入によって決定される
- Exit Functionステートメントで関数の動作は中断される
さて、これとほぼ同等のプログラムをVB.NETでも記述することができる(リスト3-11)。
1: Private Function test() As String
2: Trace.WriteLine("start")
3: test = "Hello!"
4: Exit Function
5: Trace.WriteLine("end")
6: End Function
7:
8: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
9: Trace.WriteLine(test())
10: End Sub |
|
リスト3-11 リスト3-10と同等の機能を記述したVB.NETのプログラム
|
これを実行すると以下のようになる。
|
リスト3-12 リスト3-11の実行結果
|
前に挙げた2点のポイントが、まったく同様に再現されていることが分かるだろう。しかし、VB.NETでは、関数から値を返す方法がもう1つある。リスト3-13は、それを記述してみた例である。
1: Private Function test() As String
2: Trace.WriteLine("start")
3: Return "Hello!"
4: Trace.WriteLine("end")
5: End Function
6:
7: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
8: Trace.WriteLine(test())
9: End Sub
|
|
リスト3-13 Returnステートメントで値を返す関数を定義したプログラム
|
これを実行すると以下のようになる。
|
リスト3-14 リスト3-13の実行結果
|
見てのとおり、まったく同じ結果が得られているが、ソース・コードが1行減っていることが分かるだろう。具体的には、リスト3-11の3〜4行目に相当する機能が、リスト3-13の3行目の1行分で実行されていることになる。
Returnステートメントのあとには式を書くことができ、これにより、関数が返す値を指定できる。つまり、Returnステートメントを用いると、以下の2つの動作がワンセットで行われるということである。
- 関数の戻り値は、Returnステートメントの引数によって決定される
- Returnステートメントで関数の動作は中断される
このようなReturnステートメントの使い方は、C/C++/Java/C#などのプログラム言語に似ている。そのため、これらのプログラム言語に親しんでいるプログラマーなら容易に理解できるだろう。そうではないプログラマーでも、Returnステートメントにはメリットがある。例えばVB 6では関数名を変更するときに、関数名だけでなく、戻り値を指定する代入文も忘れずに書き直す必要があった。しかし、Returnステートメントを用いれば、関数名は関数の先頭に1回書くだけでよく、多少手間が減ることになる。また、常に戻り値の指定と関数の終了がワンセットで記述されるため、戻り値を設定することなく、Exit Functionステートメントを実行してしまう危険を減らすことができる。