連載

プロフェッショナルVB.NETプログラミング

第31回 残されたいくつかのトピック(その2)

(株)ピーデー
川俣 晶
2003/01/11

Page1 Page2 Page3

列挙型とその値

 列挙型は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

 これを実行すると以下のようになる。

 1:  0
 2:  1
サンプル・プログラム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

 これを実行すると以下のようになる。

 1: alpha
 2: beta
サンプル・プログラム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

 これを実行すると以下のようになる。

 1: alpha
 2: beta
サンプル・プログラム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

 これを実行すると以下のようになる。ただし、最後の数値は、フォームが表示された座標位置によって値が変化する。

 1: 123
 2: 456
 3: 22
サンプル・プログラム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

 これを実行すると以下のようになる。

 1: 5
サンプル・プログラム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属性の引数に指定された条件付き定数(条件付きコンパイル定数)によって判断される。このあたりは、条件付きコンパイルと同様である。


 INDEX
  連載 プロフェッショナルVB.NETプログラミング
  第31回 残されたいくつかのトピック(その2)
    1.値型と参照型/文字列の振る舞いの違い/プリミティブ型のエイリアス
  2.列挙型とその値/読み取り専用変数/複合代入ステートメント/条件付きメソッド
    3.マルチスレッドを同期するSyncLockステートメント
 
「プロフェッショナルVB.NETプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間