我可以在互联网上看到很多VB.Net模块与c#.Net Static Classes相同.我还可以读到接近a的东西Static Class是一个看起来像这样的类:
'NotInheritable so that no other class can be derived from it
Public NotInheritable Class MyAlmostStaticClass
'Private Creator so that it cannot be instantiated
Private Sub New()
End Sub
'Shared Members
Public Shared Function MyStaticFunction() as String
Return "Something"
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
我觉得这个代码很重要,可以起草,也可以阅读.使用Module这样的东西我会更舒服:
Public Module MyEquivalentStaticClass
Public Function MyStaticFunction() as String
Return "Something"
End Function
End Module
Run Code Online (Sandbox Code Playgroud)
但是,如果Module您松散了一级Namespace层次结构,并且以下3个语句相同:
'Call through the Class Name is compulsory
Dim MyVar as String = Global.MyProject.MyAlmostStaticClass.MyStaticFunction()
'Call through the Module Name is OPTIONAL
Dim MyVar as String = Global.MyProject.MyEquivalentStaticClass.MyStaticFunction()
Dim MyVar as String = Global.MyProject.MyStaticFunction()
Run Code Online (Sandbox Code Playgroud)
我发现这非常不方便,这要么污染Intelisense,要么强迫我创建额外的水平Namespace,这意味着更多的Module声明,即更多的Intelisense污染.
有没有解决方法,或者如果你想避免沉重的SharedMembers-NotInheritable-PrivateNew Class声明,这是否需要付出代价?
附加参考文献包括Cody Gray的非常好的帖子:https://stackoverflow.com/a/39256196/10794555
不,没有完全等同于VB.NET中的C#静态类.如果VB能够将Shared修饰符添加到类声明中会很好,如下所示:
Public Shared Class Test ' This won't work, so don't try it
' Compiler only allows shared members in here
End Class
Run Code Online (Sandbox Code Playgroud)
但是,不幸的是,事实并非如此.如果这样做,编译器会给您以下错误:
类不能声明为"共享"
这给我们留下了您列出的两个选项:
Shared成员的不可实例化的类(没有编译器强制执行该规则的安全性),或者Module,Shared即使您没有通过Shared修饰符明确说明,也会生成所有内容正如你所说,许多人不喜欢丢失所需的类名,作为一种额外的命名空间层,所以他们更喜欢Class只有Shared成员而不是Module.但是,这是一个偏好问题.
值得一提的是,虽然你没有要你到处调用它的成员指定的模块名称,你可以一直做下去,如果你想:
MyModule.MyMethod()
Run Code Online (Sandbox Code Playgroud)
正如你雄辩地称之为"SharedMembers-NotInheritable-PrivateNew Class",它是与静态类最接近的,它只是在功能上等同.如果使用反射,您将看到该类型的属性不同.例如,在VB中:
Module MyModule
Public Sub Main()
Dim t As Type = GetType(MyClass)
End Sub
End Module
Public NotInheritable Class MyClass
Private Sub New()
End Sub
Public Shared Sub MyMethod()
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
如果你看看t.Attributes,你会发现它等于Public Or Sealed.所以MyClass类型是密封的(NotInheritable)和公共的.但是,如果您在C#中执行此操作:
class Program
{
static void Main(string[] args)
{
Type t = typeof(Test);
}
}
public static class MyClass
{
public static void MyMethod()
{ }
}
Run Code Online (Sandbox Code Playgroud)
而你t.Attributes再次检查,这次,价值是Public | Abstract | Sealed | BeforeFieldInit.那不一样.既然你不能声明在VB中的一类既NotInheritable和MustInherit在同一时间,你有没有正好复制那个东西的机会.因此,虽然它们或多或少是等价的,但类型的属性是不同的.现在,只是为了好玩,让我们试试这个:
Module MyModule
Public Sub Main()
Dim t As Type = GetType(MyModule)
End Sub
End Module
Run Code Online (Sandbox Code Playgroud)
现在,t.Attributes模块是Sealed.而已.只是Sealed.所以这也不一样.在VB中获取真正静态类的唯一方法(意思是,通过反射检查时类型具有相同的属性)是将其写入C#类库,然后在VB中引用该库.
根据迄今为止举行的所有讨论,并感谢 Steven Doggart 的投入和 TnTinMn 的评论,我得出以下广泛的反馈和指导方针。
Static关键字用于 C#.Net,而不是 VB.Net。VB 的等价物是Shared,但SharedVB 不允许使用类(仅限成员)。下面描述的准则是尝试在 VB 中实现接近 C# 的东西Static Class。由于此类 VB 类不能是静态的Shared,因此它们被描述为“静态”。Namespace(始终称为“MySpace”),这样就不会混淆Namespace示例位于哪一层:它们都在 MySpace 层中。MySpace 层不是强制性的,可以根据您的需要删除。使用 aModule但不依赖名称Module作为Namespace图层。相反,将路径完全集成到Namespace声明中,例如:
Namespace MySpace.MyStaticClass
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Run Code Online (Sandbox Code Playgroud)
然后应该通过以下方式访问静态“成员”Global.MyProject.MySpace.MyStaticClass.MyStaticFunction()
Namespace注意:根据您所在的位置,部分路径可以被删除。通常,MySpace.MyStaticClass.MyStaticFunction()
就足够了。_Module名称Module将减少 Intelisense 下拉列表中模块的外观,但又可以清楚地表明这是一个模块。在这种情况下,上述一般风格将产生:
Namespace MySpace.MyStaticClass
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Namespace MySpace.MyStaticClass.MyStaticSubClass1
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Namespace MySpace.MyStaticClass.MyStaticSubClass2
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Run Code Online (Sandbox Code Playgroud)
这很快就会变得很重,因为它需要为每个“封装”“静态类”单独的命名空间声明。缺点包括:
Namespace架构/树状结构会不太直观:在上面的示例中,这意味着检查所有包含“MyStaticClass”的声明。Namespace声明,起草工作繁重。Namespace将需要更改多个Namespace声明:在上面的示例中,这意味着更改 'MyStaticClass' 3 次。(右键单击/重命名是您最好的朋友)另一种方法是使用带有共享成员的封装类:
Namespace MySpace
Public Class MyStaticClass
Public Function MyStaticFunction()
Return "Something"
End Function
Public Class MyStaticSubClass1
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public Class MyStaticSubClass2
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Class
End Namespace
Run Code Online (Sandbox Code Playgroud)
import命名空间,而不是import类,因此封装类通常会“强制”依赖封装类的完整路径:MyStaticClass.MyStaticSubClass1。您不能将 a 封装Module在另一个 中Module,但始终可以使用 a 的混合体,Module其中封装一个或多个类和子类。下面的示例实现了与上面示例类似的效果:
Namespace MyStaticClass
Public Module _Module
Public Function MyStaticFunction()
Return "Something"
End Function
Public Class MyStaticSubClass1
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public Class MyStaticSubClass2
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Module
End Namespace
Run Code Online (Sandbox Code Playgroud)
如果您的最终产品是一个 DLL,您打算与更广泛的受众共享,建议您在“静态”类周围设置安全网。虽然这不会影响编译器如何查看您的代码,但它将防止其他人犯错误,或者至少快速触发错误并协助快速调试:
Class NotInheritable, 以便没有人尝试Class从 Static派生 a Class:派生此类类通常是无用的。NewCreator 声明Private,以便没有人尝试实例化Class:StaticClass不应包含任何非 Static( Shared) 成员;如果是这样,那就是一个拼写错误,尝试实例化非共享成员可能会带来问题。下面的示例实现了与上面示例类似的效果:
Namespace MySpace
Public NotInheritable Class MyStaticClass
Private Sub New()
End Sub
Public Function MyStaticFunction()
Return "Something"
End Function
Public NotInheritable Class MyStaticSubClass1
Private Sub New()
End Sub
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public NotInheritable Class MyStaticSubClass2
Private Sub New()
End Sub
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Class
End Namespace
Run Code Online (Sandbox Code Playgroud)
A<System.Runtime.CompilerServices.Extension()>只能在Module块内声明。然而,Module名称对扩展没有影响,因此这个主题在这里并不真正相关。
请参阅 Peter Macej 提供的链接:https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/procedures/extension-methods