Mar 28, 2014 at 10:18 PM
Edited Sep 10, 2014 at 5:38 PM
VB Language Design Meeting 2014-02-10
C# lets you have "static class" but VB only has "Module" which lifts all its members into the namespace. Discussion on this was prompted by a comment of MVP Jan Záruba (Đonny) who said
I use Partial Private Sub New to achieve the same effect as in C# with static class. The advantage of this compared to Module is that static class does not "pollute" namespaces with it's members (and I also cannot have generic module anyway)."
Đonny encountered a known and approved Roslyn breaking change, where VS2013 let you write "private partial sub new", but Roslyn doesn't. This is by design. But the question is, what could he and other users do?
Language designer Anthony D. Green looked into it:
Today VB’s modules behave very much like F#’s modules when the AutoOpen attribute is applied. I’m proposing adding a modifier “Explicit” to modules which will go the other way. Additionally, we’d considered changing the codegen of VB Modules to
exactly match those of C# (both abstract and sealed) so that they could be recognized by C# in Dev10. Unfortunately this turned out to be a breaking change due to a bug in the XmlSerializer. With my proposal we could consider changing the metadata representation
to match C# and could also map C# static classes back to Explicit Modules. If C# does end up accepting the static import feature but retains the restriction to static classes it’ll be important to have a way for VB code to easily create such things – otherwise
C# won’t be able to consume them (e.g. the Roslyn VB SyntaxFactory module).
C# static classes are currently emitted as
.class private abstract auto ansi sealed beforefieldinit
VB modules are currently emitted as
[StandardModule] .class private auto ansi sealed
- How do you declare something whose name is hidden and whose members are lifted to the enclosing namespace?
** VB: <HideModuleName>
** C#: not available
** F#: not available
- How do you declare something where people have to qualify member access, unless they specifically import them all?
** VB: NOT POSSIBLE, BUT DESIRABLE
** C#: new C#/Roslyn feature, "static usings"
** F#: this is the default
- How do you declare something which always requires qualification to access members?
** VB: not available
** C#: this is the default
** F#: [<RequiresQualification>]
There's a clear VB parity gap here, which has been asked-for many times on user-voice and connect.
Anthony's proposal is for "static classes", no more, no less. The question is (1) whether to allow it, (2) whether to call it "explicit module" or "shared class" or something.
RESOLUTION: yes, we should allow it.
We need a new keyword or keyword pair. Here are the candidates we came up with.
RESOLUTION: We'll use "strict module" as the best of a bad bunch. We're open to suggestions for better names.
The metadata we emit for "Strict Module" should be the same as the metadata for C# static classes.
Q. Generics? We could say "strict modules" can be generic. Note: you also can't have generic modules in VB.
RESOLUTION: Strict modules CAN be generic; however generic modules CANNOT contain extension methods.
Q. Nesting? Currently VB modules can't be nested. C# static classes can be nested.
RESOLUTION: Strict modules cannot be nested.
Q. For C#/Roslyn new feature, when they import static types, will they also allow importing VB modules?
RESOLUTION: up to C#
Q. How about VB importing C# static classes?
RESOLUTION: Currently, VB can import C#'s static classes, and if they come with [StandardModule] then we auto-open. We will continue to do this. NOTE: THIS IS A BREAKING CHANGE: e.g. you will no longer be able to declare variables of type "Console".
Doesn't seem a very bad breaking change.
Q. What about <HideModuleName>?
A. Intellisense will ignore this attribute on strict modules.