連載
プロフェッショナルVB.NETプログラミング
第31回 残されたいくつかのトピック(その2)
(株)ピーデー
川俣 晶
2003/01/11
|
|
列挙型とその値
列挙型はVB 6にも存在する機能だが、VB.NETでは挙動が変わっている。それを確かめるために、サンプル・プログラムを作成してみた。まず、VB 6で記述した例を見てみよう。
1: Enum SampleEnumType
2: alpha = 0
3: beta = 1
4: End Enum
5:
6: Private Sub dump(ByVal e As SampleEnumType)
7: Debug.Print e
8: End Sub
9:
10: Private Sub Form_Load()
11: dump SampleEnumType.alpha
12: dump SampleEnumType.beta
13: End Sub
|
|
列挙型を使用したVB 6のサンプル・プログラム5 |
これを実行すると以下のようになる。
それではVB.NET用に書き換えてみよう。以下のサンプル・プログラムがそれだ。
1: Enum SampleEnumType
2: alpha = 0
3: beta = 1
4: End Enum
5:
6: Private Sub dump(ByVal e As SampleEnumType)
7: Trace.WriteLine(e)
8: End Sub
9:
10: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
11: dump(SampleEnumType.alpha)
12: dump(SampleEnumType.beta)
13: End Sub
|
|
列挙型を使用したVB.NETのサンプル・プログラム6 |
これを実行すると以下のようになる。
見てのとおり、VB 6では数値が表示されたが、VB.NETでは名前が表示された。VB.NETでも、内部的に列挙型は数値で処理されることに変わりはない。しかし、文字列に変換される際に、数値ではなく名前を返すような動作を行うようになっている。明示的にこの動作を行う場合はToString()メソッドを呼び出す。VB 6のように、数値を取り出すには、以下のようにdumpメソッドを書き換える。
6: Private Sub dump(ByVal e As SampleEnumType)
7: Trace.WriteLine(CInt(e))
8: End Sub
|
|
列挙型の値を数値で表示するように書き換えたdumpメソッド |
このようにCInt関数でキャストして整数として扱えば、数値として出力される。
このほか、いくつかの列挙型に関するトピックを見て見よう。以下のサンプル・プログラムを見ていただきたい。
1: Enum SampleEnumType As Byte
2: alpha = 0
3: beta = 1
4: End Enum
5:
6: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
7: Dim s As String
8: For Each s In System.Enum.GetNames(GetType(SampleEnumType))
9: Trace.WriteLine(s)
10: Next
11: End Sub
|
|
列挙型に含まれる名前の一覧を表示するサンプル・プログラム7 |
これを実行すると以下のようになる。
このサンプル・プログラムで注目すべき点は2つある。1つは、1行目に付加されたAs Byteというデータ型指定である。これは列挙型の値を格納する整数のデータ型を指定するものである。この例なら、たかだか0と1を示すだけでよいので、Byte型で十分である。Integer型などより大きな表現力を持つ整数型を使う必要はない。これにより、この列挙型の配列などを確保したとき、メモリの節約になる。Integer型は32bitで記憶するが、Byte型は8bitで記憶するためである。もう1つは、8行目にあるSystem.Enumクラスのインスタンスを活用していることである。このクラスには、列挙型を活用するための機能が含まれている。GetNamesメソッドは、列挙型に含まれる名前の一覧を、文字列の配列として返す機能を持っているものである。
読み取り専用変数
変数を宣言する際に、ReadOnlyキーワードを付けることで、読み取り専用の変数を宣言することができる。以下はそれを利用したサンプル・プログラムである。
1: Public Class A
2: Public Const C = 123
3: Public ReadOnly R1 As Integer = 456
4: Public ReadOnly R2 As Integer
5: Public Sub New(ByVal initialValue As Integer)
6: R2 = initialValue
7: End Sub
8: End Class
9:
10: Public Class Form1
11: Inherits System.Windows.Forms.Form
12:
13: …Windows フォーム デザイナで生成されたコード…
14:
15: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
16: Dim n As New A(Me.Left)
17: Trace.WriteLine(n.C)
18: Trace.WriteLine(n.R1)
19: Trace.WriteLine(n.R2)
20: End Sub
21: End Class
|
|
読み取り専用の変数を使用したサンプル・プログラム8 |
これを実行すると以下のようになる。ただし、最後の数値は、フォームが表示された座標位置によって値が変化する。
読み取り専用の変数は、初期化以外のタイミングで値を書き換えることはできない。初期化のタイミングとは、3行目のような宣言に付加された初期化構文や、6行目のようなコンストラクタの内部である。問題は、値を指定したら書き換えられないとすれば、2行目のような定数の宣言と何が違うのかという点である。これは、4行目で宣言されたR2の値を見れば分かるだろう。R2の値は、16行目のMe.Left、つまりフォームの左側の座標値で初期化される。これは、起動する状況によって値が変わるもので、一定しているわけではない。つまり、定数は常に値が同じだが、読み取り専用の変数は実行するごとに違う値を取ることができるわけである。
複合代入ステートメント
変数aに対して「a = a + b」と記述して値bを足すのはよくあることである。このような場合、VB.NETでは、「a += b」という短い記述方法(複合代入ステートメント)を使うことができる。以下はそれを利用したサンプル・プログラムである。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim a As Integer
3: a = 1
4: a += 2
5: a *= 4
6: a /= 2
7: a -= 1
8: Trace.WriteLine(a)
9: End Sub
|
|
複合代入ステートメントを使用して演算を行っているサンプル・プログラム9 |
これを実行すると以下のようになる。
例えば、5行目の「a *= 4」は、「a = a * 4」と同じことである。同様に、6行目の「a /= 2」は「a = a / 2」と同じことである。この機能では、^、*、/、\、+-、&の演算子で利用できる。
条件付きメソッド
メソッドを呼び出すときに、呼び出されるメソッドにSystem.Diagnostics.ConditionalAttribute属性が設定されている場合、それは条件付きメソッドと呼ばれるものになる。以下は、条件付きメソッドを使用したサンプル・プログラムである。
1: Public Class Form1
2: Inherits System.Windows.Forms.Form
3:
4: …Windows フォーム デザイナで生成されたコード…
5:
6: <Conditional("Debug")> Private Sub sample()
7: Trace.WriteLine("Hello")
8: End Sub
9:
10: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
11: Trace.WriteLine("call sample")
12: sample()
13: Trace.WriteLine("sample done")
14: End Sub
15: End Class
|
|
条件付きメソッドを使用したサンプル・プログラム10 |
これをDebugビルドで実行すると以下のような結果になる。
1: call sample
2: Hello
3: sample done
|
|
サンプル・プログラム10をDebugビルドで実行した場合の実行結果 |
これをReleaseビルドで実行すると以下のような結果になる。
1: call sample
2: sample done
|
|
サンプル・プログラム10をReleaseビルドで実行した場合の実行結果 |
見てのとおり、ビルドの設定によって、結果が異なっていることが分かるだろう。その点で条件付きコンパイルと似ているが、メソッド単位で効力を発揮するという点で、条件付きコンパイルとは異なるものである。
メソッド呼び出しが可能かどうかの判断は、System.Diagnostics.ConditionalAttribute属性の引数に指定された条件付き定数(条件付きコンパイル定数)によって判断される。このあたりは、条件付きコンパイルと同様である。