47

I'm just curious to know that there is the (Name) property, which represents the name of the Form class. This property is used within the namespace to uniquely identify the class that the Form is an instance of and, in the case of Visual Basic, is used to access the default instance of the form.

Now where this Default Instance come from, why can't C# have a equivalent method to this.

Also for example to show a form in C# we do something like this:

// Only method
Form1 frm = new Form1();
frm.Show();

But in VB.Net we have both ways to do it:

' First common method
Form1.Show()

' Second method
Dim frm As New Form1()
frm.Show()
  1. My question comes from this first method. What is this Form1, is it an instance of Form1 or the Form1 class itself? Now as I mentioned above the Form name is the Default instance in VB.Net. But we also know that Form1 is a class defined in Designer so how can the names be same for both the Instance and class name? If Form1 is a class then there is no (Static\Shared) method named Show(). So where does this method come from?

  2. What difference they have in the generated IL?

  3. And finally why can't C# have an equivalent of this?

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
Shekhar_Pro
  • 18,056
  • 9
  • 55
  • 79
  • 2
    "What difference they have in the generated IL": Download and use .NET Reflector to find out for yourself. It is tremendously useful, and free. – Merlyn Morgan-Graham Jan 15 '11 at 08:03
  • 3
    I wouldn't want this "feature" in C#... It's just a trick to hide the fact that you need to create an instance of a class to use it. It's really a terrible idea! Plus, it's very poorly documented, and has unexpected and dangerous side effect (e.g. each thread has its own "default instance" of te form) – Thomas Levesque Jun 09 '12 at 20:57
  • @ThomasLevesque i don't want that feature.. i just wanted to know how its done and is it possible.. :) – Shekhar_Pro Jun 11 '12 at 08:42

2 Answers2

38

This was added back to the language in the version of VB.NET that came with VS2005. By popular demand, VB6 programmers had a hard time with seeing the difference between a type and a reference to an object of that type. Form1 vs frm in your snippet. There's history for that, VB didn't get classes until VB4 while forms go all the way back to VB1. This is otherwise quite crippling to the programmer's mind, understanding that difference is very important to get a shot at writing effective object oriented code. A big part of the reason that C# doesn't have this.

You can get this back in C# as well, albeit that it won't be quite so clean because C# doesn't allow adding properties and methods to the global namespace like VB.NET does. You can add a bit of glue to your form code, like this:

public partial class Form2 : Form {
    [ThreadStatic] private static Form2 instance;

    public Form2() {
        InitializeComponent();
        instance = this;
    }

    public static Form2 Instance {
        get {
            if (instance == null) {
                instance = new Form2();
                instance.FormClosed += delegate { instance = null; };
            }
            return instance;
        }
    }
}

You can now use Form2.Instance in your code, just like you could use Form2 in VB.NET. The code in the if statement of the property getter should be moved into its own private method to make it efficient, I left it this way for clarity.

Incidentally, the [ThreadStatic] attribute in that snippet is what has made many VB.NET programmers give up threading in utter despair. A problem when the abstraction is leaky. You are really better off not doing this at all.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • sure i won't do it ;).. Thanx a lot for your *glue* it gave me a better understanding of what made it happen. – Shekhar_Pro Jan 15 '11 at 11:52
  • 3
    An important reason why it was added into VB.Net was to help port existing code from VB1-3 to VB.Net, where the feature will have been used because there was no alternative. That's why I am pleased it was added: personally I don't think it should be used in new code. Also despite my support for this feature and some experience with VB6, I don't think I personally have any problems understanding the difference between a type and a reference to an instance of the type :) – MarkJ Jan 17 '11 at 13:12
  • 2
    So basically the VB.NET language was modified because the users were too stupid to understand OOP... I'm always amazed at how this language manages to be flawed in so many ways, while still having almost the same features as C#. – Thomas Levesque Jun 09 '12 at 21:00
  • 16
    @ThomasLevesque: *'too stupid to understand OOP'*? No, and I'd recommend you cease that line of thought. Hans Passant's answer indicates that classes didn't exist in VB till VB4 so this feature needed to be put in VB.NET to ease project upgrades from VBX to VB.NET. If you've tried upgrading any non-trivial VBX application to VB.NET, you'll know how many errors you're likely to get and you'll appreciate any 'non-standard' language adaptation that reduces developers' workload. Yes, MarkJ is right, it shouldn't be used in new code but VB devs are definitely not stupid else they'd not be around. – Alex Essilfie Sep 03 '13 at 07:03
  • 1
    @AlexEssilfie, I'm not saying that VB.NET users *are* too stupid, I'm saying that the language was designed as if they were. I understand the need for compatibility with older code, but this should be an optional feature that you enable explicitly, certainly not the default for new projects. – Thomas Levesque Sep 03 '13 at 07:39
  • 1
    Some links to documentation. The VB6 documentation explains it [here](http://msdn.microsoft.com/en-us/library/aa262343(v=vs.60).aspx). The VB.net documentation mentions it briefly [here](http://msdn.microsoft.com/en-us/library/vstudio/87y2hdsf.aspx). It's explained in this [MSDN technical article on VB2005](http://msdn.microsoft.com/en-us/library/ms379610(v=vs.80).aspx#vbmy_topic3) under `My.Forms`. And I still say the main reason it was added to VB.Net was to assist in porting legacy VB6 code, not because VB6 coders had crippled minds :) – MarkJ Nov 20 '13 at 18:17
  • 5
    Horrible crimes are being committed in the name of higher ideals. For example, `Option Strict Off` – Steve Nov 04 '14 at 10:45
  • 1
    There's a little bug in the code above leading to the StackOverflowException. There should be "if (instance == null) {" in the first line of getter instead of There should be "if (Instance == null) {". – Szybki Mar 21 '16 at 09:22
  • VB's weird automatic workarounds are dreadful. I once caught it accepting a wrong parameter type on a function call. It just tried to convert it on-the-fly in runtime. Which of course meant the error made it _crash_ on the _user's_ machine instead of preventing _compilation_ on _mine_, as it should... – Nyerguds Feb 28 '18 at 14:37
  • Is the `instance = this;` line in the constructor not going to open up a whole bunch of potential issues? >form opens on load >second instance of form needs to be opened due to some user input >`Instance` returns first form >`ShowDialog()` called on already shown form >`InvalidOperationException` occurs. There are other issues potentially caused by this - I just outlined one. – IAmJersh Nov 20 '19 at 11:31
29

VB is adding a load of code into your project behind your back, basically.

The easiest way to see what's going on is to build a minimal project and look at it with Reflector. I've just created a new WinForms app with VB and added this class:

Public Class OtherClass    
    Public Sub Foo()
        Form1.Show()
    End Sub
End Class

The compiled code for Foo looks like this when decompiled as C#:

public void Foo()
{
    MyProject.Forms.Form1.Show();
}

MyProject.Forms is a property in the generated MyProject class, of type MyForms. When you start diving into this you see quite large amounts of generated code in there.

C# could do all of this, of course - but it doesn't typically have a history of doing quite as much behind your back. It builds extra methods and types for things like anonymous types, iterator blocks, lambda expressions etc - but not in quite the same way that VB does here. All the code that C# builds corresponds to source code that you've written - just cleverly transformed.

There are arguments for both approaches, of course. Personally I prefer the C# approach, but that's probably no surprise. I don't see why there should be a way of accessing an instance of a form as if it was a singleton but only for forms... I like the language to work the same way whether I'm using GUI classes or anything else, basically.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194