VB.NET中的类与模块


157

在VB.NET中使用模块而不是具有共享成员函数的类是否被认为是可接受的做法?

我倾向于避免使用Modules,因为它们感觉像Visual Basic 6.0中留下的剩余物,似乎不再适合使用。另一方面,使用模块和仅具有共享成员的类之间似乎并没有太大区别。我并不是真的经常需要这两者,但有时在某些情况下它们会提供简单的解决方案。

我很想知道您是否有任何一种意见或偏爱。


10
关于模块的一个有趣之处在于,默认情况下,内部声明的方法和函数具有模块的保护级别,这意味着如果您忘记显式添加Private限定符,可能会无意间使方法可用。在一个类中,默认保护级别是私有的,除非您不了解,否则它可能会使行为混乱。
yu_ominae 2012年

Answers:


207

Module与C#static类的VB对应。当你的类仅设计用于辅助功能和扩展方法,你希望允许继承实例,您可以使用Module

顺便说一句,使用Module并不是真正的主观,也不不推荐使用。确实,您必须Module在适当的时候使用a 。.NET Framework本身可以执行多次(System.Linq.Enumerable例如)。要声明扩展方法,需要使用Module


7
完全正确,尽管我可以使用私有构造函数来防止实例化和NotInheritable修饰符。比普通的旧模块略难看,但效果相同。感谢您指出在框架中使用模块的指针;我会调查的。
汤姆·于尔根斯

8
在后台,它们只是被编译为具有[StandardModule]属性的类。另外,使用模块会强制您不要在非共享内容中拥有好东西。
Mehrdad Afshari

18
模块与C#中的静态类不同。如果模块中的方法位于导入的名称空间中,则它们实际上是全局的。
JaredPar

2
@JaredPar:我的措辞可能不好。我应该说C#静态类的VB对应物。从该声明中,我的意思是说使用Module在使用C#编写静态类的地方很有意义。
Mehrdad Afshari

3
@ Chiwda请参阅msdn.microsoft.com/en-us/library/bb384936.aspx:“扩展方法只能在模块内声明。”
Mehrdad Afshari'8

34

我认为最好避免使用模块,除非您将模块粘贴到单独的命名空间中。因为在Intellisense中,模块的方法将在该命名空间的任何位置可见。

因此,不是ModuleName.MyMethod()您最终会MyMethod()在任何地方出现弹出窗口,而是这种封装无效。(至少在编程级别上)。

这就是为什么我总是尝试使用共享方法创建Class的原因,看起来好多了。


6
同意,我目前正在使用一个带有类和模块的旧程序(可能是VB6到VB.NET 1端口)。在大约十个不同的模块中有数百个全局变量,子函数和函数,要找出起源于何处以及如何对其进行修改,真是令人难以置信。
yu_ominae 2012年

好的,这很老了,但与我的问题有关。我不是 VB专家,但我必须与之合作。我正在尝试分解一个大类(> 46,000行),因为IntelliSense / ReSharper刚刚死了。我发现使用Modules并只是将大块功能提取到自己的Module中似乎可行,但我想知道是否也应为每个模块提供自己的命名空间。那有必要吗?也就是说,仅使用模块会加快IntelliSense的速度,还是命名空间会提供更多帮助?
哥打

27

绝不弃用模块,并且在VB语言中大量使用了模块。这是在VB.Net中实现扩展方法的唯一方法。

具有静态成员的模块和类之间有一个巨大的区别。只要模块在当前名称空间中可用,就可以全局访问在模块上定义的任何方法。实际上,模块允许您定义全局方法。只有共享成员的类无法做到这一点。

这是一个简单的示例,我在编写与原始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
扩展方法...我一直想使用的另一个出色功能,但从未真正实现过-很好,这给了我另一个很好的机会。我确实了解全局范围,并且全局可用的方法当然可以方便,但是我对于过度使用它们感到有些不安。无论如何,到目前为止所有的答案都告诉我,我不应该一味地抛弃模块。有充分的理由在适当的情况下使用它们。
汤姆·于尔根斯

12

可以使用ModuleModule不能代替ClassModule达到自己的目的。的目的Module是用作容器

  • 扩展方法,
  • 并非特定于任何变量Class,或
  • 不适用于任何变量Class

Module不像一个,Class因为你不能

  • 从继承Module
  • 实施InterfaceModule
  • 也不创建的实例Module

a内的任何内容Module都可以直接在Module程序集中访问,而无需Module通过其名称引用。默认情况下,对于一个访问级别ModuleFriend


11

班级

  • 类可以实例化为对象
  • 每个实例化对象的对象数据都单独存在。
  • 类可以实现接口
  • 在类中定义的成员在该类的特定实例作用域,并且仅在对象生存期内存在。
  • 要从类外部访问类成员,必须使用Object.Member格式的完全限定名称

模组

  • 模块不能实例化为对象,因为标准模块数据只有一个副本,所以当程序的一部分更改标准模块中的公共变量时,整个程序都将看到该副本。
  • 默认情况下,在模块中声明的成员可以公开访问
  • 任何可以访问该模块的代码都可以访问它。
  • 这意味着标准模块中的变量实际上是全局变量,因为它们在项目的任何位置都是可见的,并且在程序的整个生命周期中都存在。

6

当我的VB.NET类之一具有所有共享成员时,我要么将其转换为具有匹配(或其他适当方式)名称空间的Module,要么使该类不可继承且不可构造:

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 MyCoolModulePublic Module MyCoolModule,<成员 Shared >, ,。End Module End Namespace
罗里·奥肯

0

模块非常适合存储枚举以及一些全局变量,常量和共享函数。它非常好,我经常使用它。声明的变量在整个项目中都是可见的。


0

必须,如果你正在创建扩展方法使用一个模块(而不是类)。在VB.NET中,我不知道其他选择。

我本人对模块有抵触性,我花了几个小时的时间试图弄清楚如何添加一些样板代码来解析嵌入式程序集,却发现Sub New()(Module)和Shared Sub New()(Class)是等效的。(我甚至不知道有一个可调用Sub New()的模块!)

因此,我只是把EmbeddedAssembly.Load和扔进AddHandler AppDomain.CurrentDomain.AssemblyResolve去,鲍勃成了我的叔叔。

附录:我还没有100%签出它,但是我有一个Sub New()在模块中以与类不同的顺序运行的标记,只是因为我不得不从外部将一些声明移到内部方法以避免这种情况错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.