|   | 
| 
 .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 記事ランキング
		
		
			本日
			月間