4

The startup sequence and handling of form instances is quite weird in VB.NET. When you refer to a form as for example Form2.Textbox1.Text = "Foo" then the CLR automatically uses the instance of the form that is created in the background and can be directly acessed through My.Forms.Form2.

I am using a WinForms application that starts up through a custom Sub Main(). Here the application is run by calling Application.Run(frmMain).

Since I have multiple forms that needs initilializing I would like to know exactly at which point the real form instances are created. Are they all created at Application.Run or are they only created when I call Form2.Show()? My startup sequence is as follows right now:

  1. Sub Main()
  2. Sub Main() calls Application.Run(frmMain)
  3. frmMain.Load calls frmNotMain.Show()

I can nowwhere find a line like My.Forms.frmNotMain = New frmNotMain, so it's not apparent where the instance is created.

Thank you in advance.

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
Jens
  • 6,275
  • 2
  • 25
  • 51

1 Answers1

4

According to MSDN:

When you access Form through My.Forms.Form1, the factory method checks to see if an instance of Form1 is already open. If it is, that instance is returned. Otherwise, an instance of Form1 is created and returned.

So essentially it is created and Sub New called just before it is shown (not created somewhere and held until needed). The link includes this code showing how it creates those default instances:

'Code ... generated by the compiler
Public m_Form1 As Form1
Public Property Form1() As Form1
    Get
        m_Form1 = Create__Instance__ (Of Form1)(m_Form1) 
        Return m_Form1 
    End Get
    Set(ByVal Value As Form1)
     If Value Is m_Form1
    Return
       End If
       If Not Value Is Nothing Then
          Throw New ArgumentException("Property can only be set to Nothing.")
       End If
       Dispose__Instance__ (Of Form1)(m_Form1)
    End Set
End Property

However, you are talking about the default ("weird") instance method which is ill-advised to begin with. This largely exists to provide compatibility with VB6 type code where you did just do myForm.Show() to instance and show a form (and probably for tinkerers who do not really understand instancing or OOP).

Forms are classes and should be treated as such by explicitly creating instances; so, generally:

Dim frm As New frmMain                ' NEW creates the instance
frm.Show

You can set a breakpoint on InitializeComponent in the form's Sub New to see when it is invoked. To create a global reference to it, like you might with any other class:

Friend frmMain As MainForm          ' no instance yet
Friend myMain As MainClass

Public Sub Main

    ' do this before any forms are created
    Application.EnableVisualStyles()

    myMain = New MainClass()
    myMain.DoStuff()

    frmMain = New MainForm()         ' instanced (NEW)

    Application.Run(frmMain)
End Sub

Likewise:

Dim frm2 = New frmNotMain       ' declare and instance

' short for:
Dim frm2 As frmNotMain          ' declare  frm2
frm2 = New frmNotMain           ' create instance

frm2.Show 

In all cases, Sub New for your form(s) would be called when you use the New operator to create a New form. VB tries to make this clear thru the repeated use of New, but with the default instance all that is actually tucked away in the form factory.

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
  • Thank you Plutonix. This explains it. I think it's worth it to go through the code and convert it to not use default instances at all. Do you maybe know if there is a compiler setting to disallow the use of these instances? – Jens Jul 23 '14 at 12:52
  • 1
    there are a number of use cases where the default instance can cause problems with just moderately complex apps. Depending on the scope, `myFrm` *may* refer to an existing instance, or it might create a whole new instance leading to all sorts of confusion. – Ňɏssa Pøngjǣrdenlarp Jul 23 '14 at 12:56
  • Very true. I like VB.NET very much but it's not always apparent what's going on in the background if one doesn't take the time to really dive into it. This can lead to very strange behaviour of the application. – Jens Jul 23 '14 at 13:02
  • @Jens - In the VB settings for the project, you can disable the "Applicaton Framework", but I'm not sure if that disallows the use of auto created instances, though. – Chris Dunaway Jul 23 '14 at 13:26
  • I have already done this anyways to use a custom entry method (Sub Main()), as I have written in my question. It doesn't change anything about default instances though. But thank you for the suggestion. – Jens Jul 23 '14 at 13:35