|
|
連載
改訂版
プロフェッショナルVB.NETプログラミング
Chapter 02 データ型の変化
株式会社ピーデー
川俣 晶
2004/03/04 |
|
|
VB.NETでは固定長文字列がサポートされない。そのため、リスト2-38のようなVB 6ソース・コードは、そのままVB.NETでは実行できない。
1: Private Sub Form_Load()
2: Dim s As String * 4
3: s = "ABCDEF"
4: Debug.Print s
5: End Sub
|
|
リスト2-38 固定長の文字列を使用したプログラム
|
これを実行すると以下のようになる。
|
リスト2-39 リスト2-38の実行結果
|
変数sは4文字分のサイズしかないので、6文字の文字列を代入しても、実際には4文字しか保存されない。
リスト2-40はVB.NETで、これとほぼ同等の機能を記述した一例である。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim s As String
3: s = LSet("ABCDEF", 4)
4: Trace.WriteLine(s)
5: End Sub
|
|
リスト2-40 リスト2-38と同等の機能を記述したVB.NETのプログラム
|
これを実行すると以下のようになる。
|
リスト2-41 リスト2-40の実行結果
|
まず、変数に固定長のサイズを与えることはできないため、代入する時点で長さを強制する必要がある。その際、ここではLSet関数を使用しているが、LSet関数は常に固定長の文字列を返すので、固定長変数と類似の結果を得やすい。LSet関数は、指定長さに足りないときは空白文字を足して長さをそろえてくれる。これに対してLeft関数は、引数に渡した文字列の長さが指定長よりも短いときは文字列をそのまま返すので(指定長よりも短い文字列を返すので)挙動が違ってくる。
さて、少々資料を調べると、VBFixedString属性により文字列の長さを指定できるという記述に出合う(属性については、属性を参照)。一見、これを使うとVB 6と同じような固定長文字列変数が確保できるかのように思えるが、実際にはできない。リスト2-42は、それを試みて失敗した例である。
1: Public Class Form1
2: Inherits System.Windows.Forms.Form
3:
4: …Windows フォーム デザイナで生成されたコード…
5:
6: <VBFixedStringAttribute(4)> Private s As String
7: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
8: '<VBFixedStringAttribute(4)> Dim s As String 'ローカル変数に属性を適用することはできません。
9: s = "ABCDEF"
10: Trace.WriteLine(s)
11: End Sub
12: End Class
|
|
リスト2-42 VBFixedString属性を使用したプログラム
|
これを実行すると以下のようになる。
|
リスト2-43 リスト2-42の実行結果
|
まず、8行目のようにローカル変数にVBFixedString属性を付けようとするとエラーになる。この属性は、フィールドにしか付かないと定義されているためだ。そこで、8行目はコメントアウトして、この定義を6行目に移動させ、フィールドとしてみた。すると、VBFixedString属性は問題なく記述し、ビルドエラーも発生しない。しかし、実行するとこの変数sには4文字以上の文字が格納されていることが分かるだろう。
結論をいえば、VBFixedString属性は入出力時の文字列の長さを指定するためのもので、固定長文字列変数を実現するためのものではない。そのため、一定の文字数以上の文字を格納できない文字列変数として使うことはできない(VBFixedString属性を活用して入出力する方法は、ランダムファイルとVBFixedString属性で解説している)。
VB 6のTypeステートメントは、VB.NETには存在しない。その代わりに、より強力な構造体という機能が用意されている。例えば、リスト2-44のようなVB 6のソースがあったとする。
1: Private Type Person
2: Name As String
3: Age As Integer
4: End Type
5:
6: Private Sub setPerson(p As Person, n As String, a As Integer)
7: p.Name = n
8: p.Age = a
9: End Sub
10:
11: Private Sub Form_Load()
12: Dim p As Person
13: setPerson p, "太郎", 17
14: Debug.Print p.Name
15: Debug.Print p.Age
16: End Sub
|
|
リスト2-44 Typeステートメントを使用したプログラム
|
これを実行すると以下のようになる。
|
リスト2-45 リスト2-44の実行結果
|
このソースをそのままVB.NETで実行することはできない。VB.NETの構造体の機能を活用して書き換えると、リスト2-46のようになる。
1: Public Class Form1
2: Inherits System.Windows.Forms.Form
3:
4: …Windows フォーム デザイナで生成されたコード…
5:
6: Private Structure Person
7: Public Name As String
8: Public Age As Integer
9: Public Sub setPerson(ByVal n As String, ByVal a As Integer)
10: Name = n
11: Age = a
12: End Sub
13: End Structure
14:
15: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
16: Dim p As Person
17: p.setPerson("太郎", 17)
18: Trace.WriteLine(p.Name)
19: Trace.WriteLine(p.Age)
20: End Sub
21: End Class
|
|
リスト2-46 Typeステートメントを構造体で書き換えたプログラム
|
これを実行すると以下のようになる。
|
リスト2-47 リスト2-46の実行結果
|
見てのとおり、いろいろな点で違っている。まず、最も重要な相違点は、VB 6ではTypeキーワードを用いているのに対して、VB.NETではStructureキーワードを用いている点である。Typeステートメントは、単なるユーザー定義型の定義手段でしかなかったが、構造体はクラスとほぼ同等の機能を持つ。つまり、構造体の中にメンバ変数としてデータを保存することもできれば、メソッドなどのコードを組み込むこともできる。上記のサンプル・ソースでは、setPersonというメソッドを、構造体の中に組み込み可能であることを示している。VB 6サンプルのsetPersonは先頭にPrivateキーワードが付いているが、VB.NETサンプルのsetPersonにはPublicキーワードが付いている。この差は、メソッドの位置が移動したことによる結果である。VB 6サンプルでは、setPersonを呼び出す側と、setPerson自身が同じフォームに属するのでPrivateで呼び出し可能である。しかし、VB.NETサンプルでは、setPersonを呼び出す側はフォームに属するが、setPerson自身はPerson構造体に属するので、Privateでは呼び出すことができない。このほか、メンバ変数の宣言にPublicキーワードが付加されている点にも注意が必要である。構造体では、PublicやPrivateのキーワードを付けることが必須となっている(構造体の必要性については、値型と参照型のパフォーマンスの相違を参照)。
業務アプリInsider 記事ランキング
本日
月間