|
|
連載
改訂版 プロフェッショナルVB.NETプログラミング
Chapter 02
データ型の変化
株式会社ピーデー
川俣 晶
2004/03/04 |
|
ここでは、主にデータ型に関係するVB 6とVB.NETの相違点についてまとめてある。VB 6のデータ型はVisual Basic固有のものであるが、VB.NETのデータ型は.NET Frameworkを通じてほかのプログラム言語と共用されるため、多くの変更が生じている。
VB.NETでは、Integerというデータ型は、System.Int32構造体のエイリアス(別名)であるとされている (構造体については、構造体宣言を参照)。従って、Integerの代わりにSystem.Int32と記述しても、まったく同等である。実際にこの2つを使い比べてみるサンプル・プログラムを記述してみた(リスト2-1)。
1: Public Class Form1
2: Inherits System.Windows.Forms.Form
3:
4: …Windows フォーム デザイナで生成されたコード…
5:
6: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
7: Dim i1 As Integer
8: Dim i2 As System.Int32
9:
10: i1 = 123
11: Trace.WriteLine(i1)
12: Trace.WriteLine(i1.GetType().FullName)
13:
14: i2 = 123
15: Trace.WriteLine(i2)
16: Trace.WriteLine(i2.GetType().FullName)
17: End Sub
18: End Class
|
|
リスト2-1 IntegerとSystem.Int32を使い比べたプログラム
|
これを実行すると以下のようになる。
1: 123
2: System.Int32
3: 123
4: System.Int32
|
|
リスト2-2 リスト2-1の実行結果
|
見てのとおり、動作に何ら差はなく、データ型のフルネームを表示させると、どちらもSystem.Int32という文字列を返す。もう1つ注目すべき点は、ソースの12行目で、Integer型の値i1に対して、型情報を取得するGetTypeメソッドを呼び出している点である。GetTypeメソッドは、本来System.Int32構造体が持っているものだが、Integer型として宣言しても、System.Int32構造体のメソッドを呼び出すことができる。
IntegerとSystem.Int32のようなエイリアス関係の名前としては、ほかにも以下の表に挙げたようなものがある。
別名 |
構造体のフルネーム |
Byte |
System.Byte |
Short |
System.Int16 |
Integer |
System.Int32 |
Long |
System.Int64 |
Single |
System.Single |
Double |
System.Double |
Decimal |
System.Decimal |
Boolean |
System.Boolean |
Date |
System.DateTime |
Char |
System.Char |
String |
System.String |
|
▼表2-3 エイリアス関係にある型名と構造体のフルネーム |
VB 6には“何でも入る魔法の箱”として、Variant型というデータ型が存在する(Variantは、さまざまの、いろいろの、という意味)。VB 6では、データ型を明示せずに宣言した変数はVariant型になるため、どんなデータを入れるにせよ、取りあえず使えるようになる。変数がVariant型であることを、ソース上にはっきり示すように記述したサンプル・ソースを以下に示す(リスト2-4)。
1: Private Sub Form_Load()
2: Dim a As Variant, b As Variant
3: a = 1
4: b = "2"
5: Debug.Print a + b
6: End Sub
|
|
リスト2-4 Variant型を明示的に宣言したVB 6のプログラム
|
さて、VB.NETではこの“何でも入る魔法の箱”をObject型と呼ぶ。そのため、VB 6でVariantと記述していた部分は、Objectと書き換えねばならない。リスト2-5はそのように記述したサンプル・ソースである。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim a As Object, b As Object
3: a = 1
4: b = "2"
5: Trace.WriteLine(a + b)
6: End Sub
|
|
リスト2-5 Variant型の代わりにObject型を使用するVB.NETのプログラム
|
この2つのソース・コードは、意味的に同じことを記述している。VariantというキーワードはVB 6までのVisual Basic専用で、VB.NETではObjectを使う。しかし、VB 6ではObjectというキーワードが別の意味で使われていたことを忘れてはならない。VB 6でのObjectは、オブジェクトを扱うデータ型であり、オブジェクトではないデータを格納するためには使用できなかった。しかし、VB.NETでは、整数などの基本的なデータ型も含め、すべてをオブジェクトとして扱えるように拡張されたので、ObjectがあればVariantは不要になったのである。
VB 6のVariantは、VB.NETではObjectに書き換えるというルールを覚えると同時に、VB 6のObjectとVB.NETのObjectは機能的に同じではないことも頭に入れておこう。
整数型は、VB 6とVB.NETの間で大きく変化している。リスト2-6とリスト2-8のサンプル・ソースを見比べていただきたい。まずは、VB 6で記述した整数型を使用するサンプル・ソースから。
1: Private Sub Form_Load()
2: Dim i1 As Integer, i2 As Integer
3: Dim l1 As Long, l2 As Long
4: i1 = -32768
5: i2 = 32767
6: l1 = -2147483648#
7: l2 = 2147483647
8: Debug.Print i1, i2, l1, l2
9: End Sub
|
|
リスト2-6 整数型を使用したプログラム
|
このサンプル・ソースでは、整数型の各データ型の最小値と最大値を代入して、確かにそれが格納可能であることを確認している。これを実行すると、以下のような結果になる。
-32768 32767 -2147483648 2147483647
|
|
リスト2-7 リスト2-6の実行結果
|
なお、ソース6行目の最後に#が付いているのは、2147483648が整数としては表現できないという理由により(正の整数の最大値は2147483647)、倍精度浮動小数点値として扱うように指示しているものだ。実行結果を見れば明らかなように、内部的にはLong型整数で-2147483648を扱うことは可能だが、ソース・コードを評価する際には「-」と「2147483648」の組み合わせとして処理されるため、エラーが起こってしまうという事情による。
さて、これと同じ趣旨のものをVB.NETで記述するとリスト2-8のようになる。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim s1 As Short, s2 As Short
3: Dim i1 As Integer, i2 As Integer
4: Dim l1 As Long, l2 As Long
5: s1 = -32768
6: s2 = 32767
7: i1 = -2147483648
8: i2 = 2147483647
9: l1 = -9223372036854775807 - 1
10: l2 = 9223372036854775807
11: Trace.WriteLine(s1 & ", " & s2 & ", " & i1 & ", " & i2 & ", " & l1 & ", " & l2)
12: End Sub
|
|
リスト2-8 リスト2-6をVB.NETで書き換えたプログラム
|
9行目がまわりくどい記述になっているが、これもリスト2-6の6行目に#が付いているのと同じ理由である。この値は大きすぎて倍精度浮動小数点でも表現できず、2つの整数を演算することで作り出している。
さて、これを実行すると以下のような結果になる。
-32768, 32767, -2147483648, 2147483647, -9223372036854775808, 9223372036854775807
|
|
リスト2-9 リスト2-8の実行結果
|
見て分かるとおり、2つの点で、大きな相違が生じている。第1の相違は、同じ名前でも表現できる数値の桁数が大幅に増えていることだ。VB 6のInteger型は、32767までしか扱うことができず、安月給の金額すらオーバーフローしてしまうのだが、VB.NETのInteger型は2147483647まで表現することができるため、相当の高給取りの給料でもオーバーフローしない表現力が与えられている。第2の相違は、Short型の創設である。Interger型の桁数が増えたことに対応して、旧Integer型に対応する範囲の値を格納するShort型が生まれた。
一見、そんなまわりくどいことをしなくても、IntegerとLongはそのままで、Longよりも大きな桁数を持つLongLongを追加すればよいと思うかもしれない。だが、取りあえず整数をIntegerで表現する習慣のあるプログラマーも多いであろうことを考えれば、最も処理効率のよい整数型をIntegerに割り当てることも悪くない選択といえる。32bit CPUであれば、32bitで表現される整数が最も効率よく扱えるので、Integerを
-2147483648〜2147483647の範囲の整数(つまり32bit符号付きの表現範囲)に変更するのは意味あることだ。
もちろん、そのような変更で桁数が減ってしまうのであれば、互換性上の問題が生じるが、桁数が増える分には、トラブルの種にもなりにくいだろう。もちろん、整数型の表現するbit数に依存するプログラミングを行っている場合は要注意である。