|
.NET TIPS
VB.NETのモジュールの正体は?
デジタルアドバンテージ 遠藤 孝信
2005/01/07 |
|
|
VB.NETには、クラスと同じようにメソッドやフィールドが定義可能な「モジュール」(VB 6.0からの慣習で「標準モジュール」と呼ばれることもある)を、Moduleステートメントを用いて定義できる。このモジュールの正体は、次のような特徴を持った特別なクラスである。
- 暗黙的にすべてのメンバがShared(共有変数や共有メソッド)となる。
- 暗黙的にクラスはNotInheritableとなる(派生クラスを記述できない)。
- インスタンス・コンストラクタを持たないので、インスタンス化することができない(コンパイラによる自動生成もなされない。コンストラクタを記述しても、それはShared(共有)コンストラクタとなる)。
.NET Frameworkのクラス・ライブラリには、例えば改行コードを定義しているモジュールとして、Microsoft.VisualBasic名前空間に次の2種類が用意されている(これらのモジュールに含まれる定数については「TIPS:複数の行を含む文字列から1行ずつ読み出すには?」でも解説している)。
- ControlCharsモジュール(Cr、Lf、CrLf、NewLineなど)
- Constantsモジュール(vbCr、vbLf、VbCrLf、vbNewLineなど)
リファレンス・マニュアルでは、これら2つの「クラス」はモジュールとして記載されているが、次のようなサンプル・プログラムを書いて実際にコンパイルしてみると、ControlCharsモジュールの方はインスタンスが作れてしまう。よって厳密にはControlCharsはモジュールではなくクラスであるといえるだろう。
Imports Microsoft.VisualBasic
Public Class CRLFTest1
Shared Sub Main()
' コンパイルOK
Dim cc As New ControlChars
' 以下の行はコンパイル・エラーとなる
Dim c As New Constants
End Sub
End Class
' コンパイル方法:vbc crlf.vb
|
|
モジュールとクラスの違いを示すサンプル・プログラム |
メンバの参照方法の違い
クラスとモジュールのもう1つの相違点は、そのメンバの参照方法である。モジュールのメンバは、そのモジュールが属する名前空間をImportsステートメントにより参照していれば、モジュール名を省略して直接メンバを参照することができる。
例えば次のサンプル・プログラムで示すように、クラスであるControlCharsの「CrLf」はコード内に直接記述できないが、モジュールであるConstantsの「vbCrLf」はそれが可能だ。
Imports System
Imports Microsoft.VisualBasic
Public Class CRLFTest2
Shared Sub Main()
' 以下の行はコンパイル・エラーとなる
Console.WriteLine(CrLf)
' コンパイルOK
Console.WriteLine(vbCrLf)
End Sub
End Class
|
|
モジュールとクラスのスコープの違いを示すサンプル・プログラム |
この場合、「CrLf」を使用するには「ControlChars.CrLf」と記述しなければならない。あるいはImportsステートメントにより「Microsoft.VisualBasic.ControlChars」を参照しておけば、CrLfを直接記述することができる(VB.NETのこの機能については「TIPS:VB.NETでクラス名を省略してメソッドや定数を利用するには?」を参照)。
StandardModule属性
上記のようなモジュール名を省略できる参照方法は、実際にはMicrosoft.VisualBasic.CompilerServices名前空間にあるStandardModule属性によるものだ。VB.NETのコンパイラは、Importsステートメントで指定された名前空間内にあるクラスにこの属性が付加されていれば、そのクラス内のメンバをチェックして、自動的に参照を追加してくれる。
Moduleステートメントを使ってモジュールを記述すると、そのモジュールにはStandardModule属性が自動的に付加されることになるが、通常のクラスに対しても明示的にこの属性を記述することにより、そのメンバの参照方法をモジュールと同等にすることができる。以下にその例を示す。
' message.vb
Namespace MyMessage
<Microsoft.VisualBasic.CompilerServices.StandardModule()> _
Public Class StandardModuleClass
Public Shared Message1 As String = "こんにちわ"
End Class
Public Class NormalClass
Public Shared Message2 As String = "さようなら"
End Class
End Namespace
' コンパイル方法:vbc /t:library message.vb
|
|
StandardModule属性を利用したサンプル・プログラム(message.vb) |
|
' scope.vb
Imports System
Imports MyMessage
Public Class ModuleScopeTest
Shared Sub Main()
Console.WriteLine(Message1)
' Console.WriteLine(Message2) ' コンパイル・エラー
Console.WriteLine(NormalClass.Message2)
End Sub
End Class
' コンパイル方法:vbc /r:message.dll scope.vb
|
|
StandardModule属性の有無による参照方法の違いを示すサンプル・プログラム(scope.vb) |
|
StandardModule属性の付いたクラスや、Moduleステートメントにより記述したモジュールは複数同時に利用することができるが、同名のメンバが複数個所で定義されている場合には、クラス名やモジュール名により、そのメンバを修飾する必要がある。
なお、StandardModule属性はC#で記述したクラスでも利用可能だ。
|
generated by
|
|
Insider.NET 記事ランキング
本日
月間