VB.NETのクラスとモジュール


157

VB.NETで共有メンバー関数を持つクラスの代わりにモジュールを使用することは許容できる方法と見なされますか?

モジュールはVisual Basic 6.0の残り物であり、実際には収まらないように思われるため、私はモジュールを避ける傾向があります。一方、共有メンバーのみのモジュールとクラスの使用には大きな違いはないようです。私が本当に必要なのはそれほど頻繁ではありませんが、それらが単純な解決策を提示する状況も時々あります。

私はあなたが何らかの方法で意見や好みを持っているかどうか知りたいです。


10
モジュールの興味深い点の1つは、デフォルトで、内部で宣言されたメソッドと関数がモジュールの保護レベルを持っていることですPrivate。つまり、修飾子を明示的に追加し忘れた場合、誤ってメソッドを使用できるようになる可能性があります。クラスでは、デフォルトの保護レベルはプライベートであり、これを意識していないと混乱を招く可能性があります。
— yu_ominae 2012

回答:


207

Modulesは、C#staticクラスに対応するVB です。クラスがヘルパー関数と拡張メソッド専用に設計されており、継承とインスタンス化を許可したくない場合は、を使用します。Module

ところで、使用Moduleは本当に主観的ではなく、非推奨ではありません。実際、Module適切な場合はaを使用する必要があります。.NET Framework自体はそれを何度も実行System.Linq.Enumerableします(たとえば)。拡張メソッドを宣言するには、Modules を使用する必要があります。


7
正解ですが、インスタンス化とNotInheritable修飾子を防ぐためにプライベートコンストラクターを使用できます。普通の古いモジュールより少し醜いですが、同じ効果があります。フレームワークでのモジュールの使用へのポインタをありがとう; 調べてみます。
— Tom Juergens、

8
内部的には、[StandardModule]属性を持つクラスにコンパイルされるだけです。また、モジュールを使用すると、共有されていないものをそこに置かずに済みます。これは良いことです。
— Mehrdad Afshari、

18
モジュールは、C#の静的クラスと同じではありません。モジュール内のメソッドは、インポートされた名前空間にある場合、事実上グローバルです。
— JaredPar 2009年

2
@JaredPar:私の言い回しはおそらく悪いです。C#の静的クラスに対応するVBを言うべきでした。そのステートメントから、モジュールを使用することは、C#で静的クラスを作成する場合に意味があると言うつもりです。
— Mehrdad Afshari、

3
@Chiwda msdn.microsoft.com/en-us/library/bb384936.aspxを参照してください:「拡張メソッドはモジュール内でのみ宣言できます。」
— Mehrdad Afshari 2012

34

モジュールを別々の名前空間に貼り付けない限り、モジュールを避け続けることは良い考えだと思います。Intellisenseでは、モジュールのメソッドはその名前空間のどこからでも見えるからです。

したがって、どこかにポップアップが表示ModuleName.MyMethod()される代わりにMyMethod()、この種のカプセル化が無効になります。(少なくともプログラミングレベルでは)。

そのため、私は常に共有メソッドを使用してクラスを作成しようとしますが、はるかに優れているようです。


6
同意して、私は現在、クラスとモジュールを使用して古いプログラム(おそらくVB6からVB.NET 1へのポート)に取り組んでいます。約10の異なるモジュールには何百ものグローバル変数、サブ、関数があり、何がどこから発生し、どこでどのように変更されたかを知るのは大変です。
— yu_ominae

これは非常に古いですが、私の質問に関連しています。私はVBの人ではありませんが、私はそれを使用する必要があります。IntelliSense / ReSharperが死ぬだけなので、私は大きなクラス(> 46,000行)を分解しようとしています。Modulesを使用していて、関数の大きなチャンクを独自のModuleにリッピングするだけでうまくいくようですが、各モジュールに独自の名前空間も指定する必要があるのではないかと思っています。それは必要でしょうか?つまり、モジュールだけでIntelliSenseを高速化できますか、それとも名前空間がさらに役立ちますか
— コダ

27

モジュールは決して非推奨ではなく、VB言語で頻繁に使用されます。これは、たとえばVB.Netで拡張メソッドを実装する唯一の方法です。

静的メンバーを持つモジュールとクラスの間には1つの大きな違いがあります。モジュールが現在の名前空間で使用できる限り、モジュールで定義されたメソッドはすべてグローバルにアクセスできます。実際には、モジュールを使用すると、グローバルメソッドを定義できます。これは、共有メンバーだけのクラスではできないことです。

これは、生のCOMインターフェイスと相互運用するVBコードを記述するときによく使用する簡単な例です。

Module Interop
  Public Function Succeeded(ByVal hr as Integer) As Boolean
    ...
  End Function

  Public Function Failed(ByVal hr As Integer) As Boolean
    ...
  End Function
End Module

Class SomeClass
  Sub Foo()
    Dim hr = CallSomeHrMethod()
    if Succeeded(hr) then
      ..
    End If
  End Sub
End Class

4
拡張メソッド...私が常に使用することを意味するもう1つの優れた機能ですが、実際には使用できません。私はグローバルスコープについて少し理解していますし、グローバルに利用可能なメソッドは確かに便利ですが、それらを使いすぎることには少し不安を感じます。とにかく、これまでのすべての答えは、手元にないモジュールを却下すべきではないと私に伝えています。適切な状況でそれらを使用する十分な理由があります。
— Tom Juergens、

12

使用しても問題ありませんModule。Moduleの代わりとしては使用されませんClass。Module独自の目的を果たします。の目的はModule、コンテナとして使用することです

  • 拡張メソッド、
  • に固有ではない変数Class、または
  • どの変数にも適切に適合しない変数Class。

Module以下のようではありませんClassので、あなたがすることはできません

  • から継承Module、
  • を実装InterfaceしModule、
  • のインスタンスも作成しませんModule。

内部のものはModule直接内でアクセスすることができるModuleを参照することなく組み立てModuleその名前によって。デフォルトでは、aのアクセスレベルModuleはFriendです。


11

クラス

  • クラスはオブジェクトとしてインスタンス化できます
  • オブジェクトデータは、インスタンス化されたオブジェクトごとに個別に存在します。
  • クラスはインターフェースを実装できます。
  • クラス内で定義されたメンバーは、クラスの特定のインスタンス内でスコープされ、オブジェクトの存続期間中のみ存在します。
  • クラスの外部からクラスメンバーにアクセスするには、Object.Memberの形式で完全修飾名を使用する必要があります。

モジュール

  • モジュールをオブジェクトとしてインスタンス化することはできません。標準モジュールのデータのコピーは1つしかないため、プログラムの一部が標準モジュールのパブリック変数を変更すると、プログラム全体に表示されます。
  • モジュール内で宣言されたメンバーは、デフォルトでパブリックにアクセスできます。
  • モジュールにアクセスできる任意のコードからアクセスできます。
  • つまり、標準モジュールの変数は、プロジェクトのどこからでも可視であり、プログラムの存続期間中存在するため、実質的にグローバル変数です。

6

私のVB.NETクラスの1つにすべての共有メンバーがある場合、それを一致する(または適切な)名前空間を持つモジュールに変換するか、クラスを継承不可能および構築不可能にします。

Public NotInheritable Class MyClass1

   Private Sub New()
      'Contains only shared members.
      'Private constructor means the class cannot be instantiated.
   End Sub

End Class

3
そして、ここで名前空間モジュールの構文です:Imports <whatever>あなたは任意の輸入を持っている場合は、Namespace MyCoolModule、Public Module MyCoolModule、<メンバーせずに Shared、> End Module、End Namespace。
— Rory O'Kane 2013

0

モジュールは列挙型といくつかのグローバル変数、定数、共有関数を格納するのに適しています。とても良いことで、よく使っています。宣言された変数は、プロジェクト全体で表示されます。


0

Extensionメソッドを作成する場合は、クラスではなくモジュールを使用する必要があります。VB.NETでは、別のオプションを認識していません。

私自身もモジュールに耐性があるため、埋め込みSub New()モジュールを1つに解決するためのボイラープレートコードを追加する方法を試すために数時間を費やしましたが、(モジュール)とShared Sub New()(クラス)が同等であることがわかりました。(モジュールにcallable があることさえ知りませんでしたSub New()!)

だから、僕は投げEmbeddedAssembly.LoadとAddHandler AppDomain.CurrentDomain.AssemblyResolveそこにラインを、ボブは私の叔父となりました。

補遺:私はまだ100%チェックアウトしていませんがSub New()、モジュール内でクラスとは異なる順序で実行されるインクリングがあります。これは、いくつかの宣言を外側から内側のメソッドに移動しなければならなかったという事実です。エラー。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.