Java/C# ユーザーが初めて VB.NET に触れた時、「Module(モジュール)って何?」という疑問にぶち当たる確率は高いと思う。
簡単に言ってしまえば、静的メンバのみのクラス(C# の static class)で、呼び出し側でクラス名(モジュール名)を省略できる特徴がある。
文字だと分かりにくいのでコードで
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Public Module ModuleSample
Sub New()
Console.WriteLine("ModuleSample.New")
End Sub
Public Sub TestCall()
Console.WriteLine("ModuleSample.TestCall")
End Sub
End Module
Module EntryPoint
Sub Main()
TestCall()
ModuleSample.TestCall()
End Sub
End Module
C# からは、static class として扱える。
1
2
3
4
5
6
7
8
9
10
11
static class EntryPoint
{
static void Main()
{
ModuleSample.TestCall();
}
}
Module の実態は static class とほぼ同じなのだが、C# の static class を VB から呼ぶ場合は Module のようにクラス名を省略できない。その違いは、
StandardModuleAttribute である。
この属性を C# の static class に付けてやると、VB から呼ぶ場合にクラス名を省略できる。
ただ、MSDN の説明に「独自に作成したコードから直接使用するためのものではありません。」「これは、コードから直接呼び出すためのものではありません。」とあり、ユーザーコードからは使って欲しくない模様・・・
1
2
3
4
5
6
7
8
9
10
11
using System;
using Microsoft.VisualBasic.CompilerServices;
[StandardModule]
public static class CShapModuleSample
{
public static void TestCall()
{
Console.WriteLine("CShapModuleSample.TestCall");
}
}
MSIL の比較
VB - Module |
.class public auto ansi sealed |
C# - static class |
.class public abstract auto ansi sealed beforefieldinit |
static class には、abstract/beforefieldinit が付いている。
static class の場合、beforefieldinit は静的コンストラクタがあると付かないが、Module の場合、コンストラクタの有無に関わらず付かない。
つまり、Module のフィールドは必ず最初のアクセス時に初期化される。(アクセスがなければ初期化されない)
拡張メソッド
VB の拡張メソッドは Module でしか作れない。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Imports System.Runtime.CompilerServices
Public Module Extensions
<Extension()>
Public Function IsNotNull(Of T)(ByVal source As T) As Boolean
Return source IsNot Nothing
End Function
End Module
Dim val = ""
val.IsNotNull()
IsNotNull(val)
Extensions.IsNotNull(val)
まとめ
Module は多用しない方がいい。
クラス名(モジュール名)を省略することは、名前の衝突確率を上げることになり、あまりよくない。
プログラムのエントリポイント、拡張メソッド以外での利用は避けた方がいい。
どうしても使いたい場合は、アクセス修飾子を Friend にする、専用の名前空間にする、などの条件を設けるべき。
余談だが、拡張メソッドも名前の衝突確率が高いので、専用の名前空間を推奨。
VB は Module があるためか、静的クラスが無いので、代わりに下記のような疑似静的クラスを使ったりする。
1
2
3
4
5
6
7
8
Public NotInheritable Class StaticClass
Private Sub New()
End Sub
End Class
検証環境
Windows 7 64bit/Visual Studio 2010 SP1/.NET 4.0