Open mansellan opened 2 years ago
I should point out that even in VBA, you already can approximate this with a predeclared class module. However, the main difference here is that a static1 class cannot be instantiated whereas a predeclared class can be also instantiated.
In VB6, you'd use a GlobalSingleUse
instancing. However because it's global, I think (but may be wrong) that it also implies appobject
behavior in which case it's no better than a standard module in terms of namespace pollution.
I suspect that the easiest way to handle this as well as the other instancing is to provide an attribute [Instancing(...)]
and creating a new instancing type in the addition to the six that VBx uses, which can be called Static
. No new keywords, no confusion, everything's still text, so happy everyone. (right?)
1. I hate the keyword Shared
-- it's not very helpful in describing what it means. A unfortunate consequence of VBx's using of Static
to mean something completely differently and needing to disambiguate the concepts here.
- I hate the keyword
Shared
-- it's not very helpful in describing what it means. A unfortunate consequence of VBx's using ofStatic
to mean something completely differently and needing to disambiguate the concepts here.
Me too, it's very unfortunate as Static
is much more widely used for this feature in other languages.
Shared
/ static
classes in other languages (like C#) are there because of lack of standard modules as in VBx as far as I understand.
In VB6, you'd use a GlobalSingleUse instancing. However because it's global, I think (but may be wrong) that it also implies appobject behavior in which case it's no better than a standard module in terms of namespace pollution.
3 - SingleUse
and 4 - GlobalSingleUse
are available only in Ax-EXE project while for Ax-DLL ones there is only 1 - Private
, 2 - PublicNotCreatable
, 5 - MultiUse
and 6 - GlobalMultiUse
.
Instancing
property maps to several VB_Xxx
attributes which have more combinations possible than the entries available in the combobox and the Instancing
property is not even available for Std-EXE projects where every class in just 1 - Private
instancing.
Here is a list of all Instancing
values possible against VB_Xxx
attributes it sets
Instancing | MultiUse | VB_GlobalNameSpace | VB_Creatable | VB_PredeclaredId | VB_Exposed |
---|---|---|---|---|---|
1 - Private | -1 | False | False | False | False |
2 - PublicNotCreatable | -1 | False | False | False | True |
3 - SingleUse | 0 | False | True | False | True |
4 - GlobalSingleUse | 0 | True | True | False | True |
5 - MultiUse | -1 | False | True | False | True |
6 - GlobalMultiUse | -1 | True | True | False | True |
Apparently there is no way to set VB_PredeclaredId
using Instancing
.
What I just found out it that it's possible to set VB_PredeclaredId = True
simultaneously with VB_GlobalNameSpace = False
which requires calling routines on the global object through its class name i.e. only MyClass.TestGlobal
works while TestGlobal
fails compilation as the methods are not available in the global namespace.
Nothing prevents instantiating a 6 - GlobalMultiUse
class in addition to the global instance provided unless this is prevented with some code in Class_Initialize
like this
Private Sub Class_Initialize()
If Not Me Is Class1 Then
Err.Raise vbObjectError, , "Singleton instantiation attempted"
End If
End Sub
I'm a big proponent of VB_GlobalNameSpace = False
for standard modules as this would allow not polluting global symbols table with for instance FFI Enums or API declares e.g. calling Win32.Sleep
as a global API declare that does no appear as Sleep
in global namespace.
Nothing prevents instantiating a 6 - GlobalMultiUse class in addition to the global instance provided unless this is prevented with some code in Class_Initialize like this
I used to do that but I came across a situation in VBA where that doesn't work and instantiating still happens anyway. I cannot remember the particulars. In other languages there are additional considerations for handling access. This old article for C# shows that naive implementation can be problematic. This does not apply in VBx because it's normally single-threaded but if tB has multi-threading, that will require some consideration.
I'm a big proponent of VB_GlobalNameSpace = False for standard modules
To clarify, is that an existing feature? I don't see VB_GlobalNameSpace
attribute when exported from a VBA module. Not sure if VB6 treats it differently. Btu I very much agree with your sentiments and would much rather have Win32.Sleep
and not just Sleep
.
Interesting, perhaps that's why Shared Class
is not a thing in VB.Net, it's just not needed.
I was mainly asking about Shared
class members though - Subs, Functions, Properties, Fields etc. It can be useful for a class to have a mixture of static and instance declarations.
Is your feature request related to a problem? Many languages (including VB.Net and C#) offer the opportunity to define class members that are available on a shared basis, rather than per-instance. In VB.Net, these are
Shared
members, which are broadly equivalent tostatic
declarations in C#.This is useful for utility functions, as it's more tightly scoped than simply using a standard module. It could go some way to alleviating the problems of not (yet) having namespaces available in tB.
Describe the solution you'd like
Describe alternatives you've considered Standard modules, but they're not as flexible. Whilst you can prefix the function name with the module name, it's entirely optional. Public functions of standard modules always go into the global namespace. Shared functions are "carried with" the class in which they are defined.
Additional context
Shared
/static
members are also the foundation of other language features in VB.Net / C#, such as operator overloading (including casting) and (in C#) extension methods.Note that in VB.Net, the
Shared
operator cannot be applied to classes, only to members. In C#, classes can be marked asstatic
, which means they can only containstatic
members. I think the restriction in VB.Net is artificial, probably to avoid confusion with standard modules. IMO, twinBASIC should allowShared
-only classes, they might even end up being generally preferred over standard modules by some.I seem to recall mention of this, but couldn't find an issue for it yet.