連載
プロフェッショナルVB.NETプログラミング
第4回 変数スコープと文字列関数
(株)ピーデー
川俣 晶
2002/04/23
|
|
変数のスコープ
VB 6では、メソッド内で定義された変数は、メソッド内全域で有効であった。そのため、Forループの内側で宣言した変数をForループの外側で参照しても問題はない。また、宣言された場所に関係なく、メソッドを脱出するまでその内容は有効であり、値を累積することも可能だった。このことを示すサンプル・ソースを以下に示す。
1: Private Sub Form_Load()
2: Dim a As Integer
3: For i = 0 To 9
4: Dim b As Integer
5: a = a + 1
6: b = b + 1
7: Debug.Print a, b
8: Next
9: Debug.Print a, b
10: End Sub |
|
変数のスコープを示すVB 6のサンプル・プログラム3 |
これを実行すると以下のようになる。
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
10 10
|
|
サンプル・プログラム3の実行結果 |
これをVB.NETに書き換えたものを以下に示す。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim a As Integer
3: Dim i As Integer
4: For i = 0 To 9
5: Dim b As Integer
6: a = a + 1
7: b = b + 1
8: Trace.Write(a)
9: Trace.Write(", ")
10: Trace.WriteLine(b)
11: Next
12: Trace.Write(a)
13: Trace.Write(", ")
14: 'Trace.WriteLine(b) '名前 'b' は宣言されていません。
15: End Sub |
|
サンプル・プログラム12をVB.NETで書き換えたサンプル・プログラム4 |
これを実行すると以下のようになる。
1, 1
2, 2
3, 3
4, 4
5, 5
6, 6
7, 7
8, 8
9, 9
10, 10
10,
|
|
サンプル・プログラム4の実行結果 |
ほとんど同じように見えるが、14行目がエラーになる点に注意が必要である。VB.NETでは、変数はスコープを持っており、Forループなどブロック構造を表記する構文の中で宣言された変数は、そのブロック構造の内側からしか利用することができない。しかし、変数にスコープを持つほかの主要な言語(C/C++/Java/C#など)とは異なり、メソッドなどを脱出するまで変数は有効という特徴は継承されており、ブロック内で宣言された変数で値を累積していくことができる。この点で、VB.NETのスコープの概念は、VB 6と異なるだけでなく、C/C++/Java/C#などとも異なるため、注意して扱う必要がある。
値を累積したくない場合は、変数宣言の直後に変数の値を初期化するコードを必ず書き込むようにすると、意図しない動作を防止できる。
文字列関連関数の相違
VB 6には文字列関連の関数に2つのバージョンを持つものがあった。例えば、Chr関数とChr$関数は別個の関数である。“$”の付くものは文字列型を扱い、“$”の付かないものはVariant型を扱う。この結果、文字列ではないデータを扱ったときに挙動が異なる場合があった。以下はこのような関数の一例としてLeft関数とLeft$関数を扱った例である。
1: Private Sub Form_Load()
2: Dim v As Variant, r As Variant
3: v = Null
4: r = Left(v, 3)
5: Debug.Print TypeName(r)
6: v = "ABCDEF"
7: r = Left$(v, 3)
8: Debug.Print TypeName(r)
9: End Sub |
|
Left関数とLeft$関数を使用したVB 6のサンプル・プログラム5 |
これを実行すると以下のようになる。
Left関数にNull値を渡すことは合法で、結果はNull値になる。しかし、Left$関数にNull値を渡すことはできない。
これをVB.NET用に書き換えたのが以下のサンプル・ソースである。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim v As Object, r As Object
3: v = Nothing
4: r = Microsoft.VisualBasic.Left(v, 3)
5: Trace.WriteLine(TypeName(r))
6: v = "ABCDEF"
7: r = Microsoft.VisualBasic.Left$(v, 3)
8: Trace.WriteLine(TypeName(r))
9: End Sub |
|
サンプル・プログラム14をVB.NETで書き換えたサンプル・プログラム6 |
これを実行すると以下のようになる。
VariantがObjectに、NullがNothingになるのは、一種のお約束である。さて肝心の結果だが、VB 6の場合とは異なっていることが分かるだろう。VB 6では2種類あった文字列関数は、VB.NETでは1種類しか存在しない。Variant型を返す関数は存在しないため、Left関数の結果は常に文字列になる。構文的にLeftのほかにLeft$という名前を記述することは可能だが、これは型指定文字としての$記号が付加されているだけで、別の関数の呼び出しになるわけではない(なお、Leftというキーワードのプロパティなどがあり紛らわしいときは、このサンプル・ソースのように、LeftのかわりにMicrosoft.VisualBasic.Leftといった長い完全修飾名の記述が必要となる場合がある)。その結果、Null(Nothing)値を引数に取った場合のLeft関数の挙動に相違が生じているわけである。文字列関連関数で、文字列以外の値を扱うことはめったにないかもしれないが、意図せざるバグによりそれを処理してしまっている可能性もある。もし、VB.NETでプログラミングしていて、文字列関連の挙動がVB 6と異なるときは、チェックしてみる価値があるだろう。
まとめ
VB.NETは、VB 6と比較してあちこち変わっていることがお分かりいただけたと思うが、決してVB.NETはVBの文法で書くC#ではない。VBらしいお約束が残されていて、C#とは異なる動作を見せる機能もある。そのため、VB 6とC#を知っているからといって、VB.NETを勉強せずに、すぐに使いこなせるというわけでもない。十分に注意しよう。
次回は日付と時刻の扱いについて解説したいと考えている。
では次回もまた会おう。
Insider.NET 記事ランキング
本日
月間