.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#で記述したクラスでも利用可能だ。End of Article

カテゴリ:Visual Basic .NET 処理対象:ステートメント
使用ライブラリ:StandardModule属性(Microsoft.VisualBasic.CompilerServices名前空間)
関連TIPS:複数の行を含む文字列から1行ずつ読み出すには?
関連TIPS:
VB.NETでクラス名を省略してメソッドや定数を利用するには?
 
この記事と関連性の高い別の.NET TIPS
VB.NETでクラス名を省略してメソッドや定数を利用するには?
VB.NET固有の関数をC#で使用するには?
[ASP.NET]アプリケーション共通のロギングを行うには?(HTTPモジュール編)
複数の行を含む文字列から1行ずつ読み出すには?
My機能を拡張して独自の機能を追加するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


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 記事ランキング

本日 月間