Why does VB allow declaring object of a static type?

时间:2016-08-31 17:14:40

标签: c# vb.net

A client has a variable declared using a static type - similar to the following test (which compiles in VB):

Dim test As System.IO.File

What is the purpose of this? In my client's code, this variable was not referenced anywhere so I couldn't follow any usage pattern. I would have expected that VB would have a problem with this declaration (as C# does), but since it doesn't I assume that there is some esoteric VB-ish purpose to this?

1 个答案:

答案 0 :(得分:7)

There is actually no such thing as a Shared class in VB.NET. (Shared is the VB.NET keyword for what we know and love as static in C#). Only member variables (fields), events, functions/subs, properties, and operators can be marked Shared. (Local variables that retain their values across invocations are not marked Shared, but rather Static. The CLR doesn't natively support these and neither does C#, but the VB.NET compiler emits the additional code necessary to make it work.)

There are two workarounds to effect the same result as a static class in VB.NET:

  1. Create a Module. Practically, this is the same as a static class. Indeed, from an IL perspective, they are identical. However, modules are treated slightly differently in the VB.NET language proper. The concept of modules was inherited from legacy COM-based VB (actually, they are much older than that, going back to early versions of BASIC)

    If you're familiar with C++ or similar languages, a module is akin to a namespace, except that all of the functions defined in a module are promoted into the outer scope (enclosing namespace), via the Microsoft.VisualBasic.CompilerServices.StandardModule attribute. A module can never be treated like a class, so any declarations of or references to a module are illegal. However, you can still (and should generally prefer) to call a function defined in a module using a fully-qualified reference (e.g., MyModule.MyFunction(...)).

  2. Create a NotInheritable class (VB.NET equivalent of C#'s abstract keyword), give it an empty Private constructor, and mark all of its methods as Shared. Note that the class itself is not actually shared/static—just the individual functions that make up that class. The compiler therefore does not enforce the rule that an instance of that class cannot be declared, because from the compiler's perspective, the class is no different than any other class.

Since the .NET BCL was written in C#, it uses option 2. All classes that were marked static are simply NotInheritable classes in VB.NET with Shared member functions and private constructors. For example, the declaration of System.IO.File appears as follows to VB.NET:

Public NotInheritable Class File
    Inherits System.Object

    ' Contains Shared methods, e.g.:

    Public Shared Sub Copy(sourceFileName As String, destFileName As String)
        ' implementation
    End Sub

    ' private constructor to prevent instantiation
    Private Sub New()
    End Sub

End Class

Note that since only instantiation is prohibited (via making the constructor private), the compiler still allows you to declare empty variables of that class type. They can never be assigned a value, of course, so they will always be equal to Nothing. (TypeOf(test) Is Nothing will return True, in this case, as will test Is Nothing, and TypeName(test) will return Nothing).