VB.NET 中的类与模块

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

我倾向于避免使用模块,因为它们感觉像是 Visual Basic 6.0的剩余部分,并且似乎不再适合。另一方面,使用模块和只使用共享成员的类似乎没有太大区别。这并不是经常,我真的有很多需要,但有时候,他们提出了一个简单的解决方案的情况。

我很想知道你有什么看法或偏好。

153620 次浏览

Module是 C # static类的 VB 对应物。当您的类仅用于帮助函数和扩展方法,并且 不要希望允许 继承遗产实例化时,可以使用 Module

顺便说一下,使用 Module并不是真正主观的,它是 没有被贬低。实际上,必须在适当的时候使用 Module。.NET 框架本身就做了很多次(例如,System.Linq.Enumerable)。要声明扩展方法,需要使用 Module

我认为避免使用模块是一个好主意,除非将它们放在单独的名称空间中。因为在 Intellisense 中,模块中的方法在该名称空间中的任何地方都是可见的。

因此,在任何地方都会弹出 MyMethod(),而不是 ModuleName.MyMethod(),这种做法会使封装失效。(至少在编程水平上)。

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

在 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

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

Public NotInheritable Class MyClass1


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


End Class

使用 Module是可以接受的。Module不用作 Class的替代品。Module有自己的用途。Module的用途是作为

  • 扩展方法,
  • 不特定于任何 Class的变量,或者
  • 不适合任何 Class的变量。

Module不像 Class,因为你不能

  • Module继承,
  • Module实现 Interface,
  • 也不创建 Module的实例。

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

课程

  • 类可以实例化为 物品
  • 每个实例化对象的对象数据分别存在。
  • 类可以 实现接口
  • 类中定义的成员是 作用域为类的特定实例,并且只存在于 对象的生存期中。
  • 要从类的外部访问类成员,必须以 反对,成员的格式使用 完全限定名称

模组

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

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

如果要创建扩展方法,则 必须的使用模块(而不是类)。在 VB.NET 中,我不知道还有其他的选择。

由于我自己对模块有抵抗力,所以我花了几个小时的时间试图解决如何添加一些样板代码来解决嵌入式程序集,结果却发现 Sub New()(模块)和 Shared Sub New()(类)是等价的。(我甚至不知道模块中有一个可调用的 曾经是!)

所以我就把 EmbeddedAssembly.LoadAddHandler AppDomain.CurrentDomain.AssemblyResolve的台词放进去然后鲍勃就成了我叔叔。

附录 : 我还没有100% 地检查它,但是我有一个暗示,Sub New()在模块中运行的顺序和在类中运行的顺序不同,这只是因为我必须从外部移动一些声明到内部方法中以避免错误。