Code Focused

Magic Forms Access in Visual Basic and C#

Look behind the curtain on this one, and you'll see that code is quite magical in and of itself.

Accessing a specific form within a Visual Basic Windows Forms application is magical. Simply naming the form in any part of your source code causes that form to--presto--magically pop into existence:

' ----- And there it is!

Behind the scenes, Visual Basic is treating the form mention as a shortcut to the My.Forms pseudo-collection:


This is a little more informative, but you still can't tell what's really going on, because it's magic. If you could peer inside the My.Forms feature, you might find Visual Basic adding parallel form access points for every Form-derived class you include in your application, as shown in Listing 1.

Listing 1: My.Forms Module 
Partial Friend Module My.Forms
  ' ----- Internal, hidden storage for the magic form.
  Private InternalForm2 As WindowsApplication1.Form2 = Nothing

  ' ----- The public face of the magic form.
  Public Property Form2 As WindowsApplication1.Form2
      ' ----- Ensure a form always appears when requested.
      If (InternalForm2 Is Nothing) Then _
        InternalForm2 = New WindowsApplication1.Form2
      Return InternalForm2
    End Get
    Set(value As WindowsApplication1.Form2)
      ' ----- Allow clearing, but not overwriting, of form.
      If (value Is Nothing) Then
        InternalForm2 = Nothing
        Throw New Exception("That's a no-no.")
      End If
    End Set
  End Property
End Module

So, it's not magic, it's just code. Which means it's just like C#, because -- and learning this is part of growing up and becoming an adult -- the C# language has no magic. It also means you can do the same kind of form-magic thing in C#, if you add similar code, as shown in Listing 2.

Listing 2: My.Forms Module a la C# 
static internal partial class MyForms
  // ----- Internal, hidden storage for the magic form.
  private static WindowsFormsApplication1.Form2 InternalForm2 = null;

  public static WindowsFormsApplication1.Form2 Form2
      // ----- Ensure a form always appears when requested.
      if (InternalForm2 == null)
        InternalForm2 = new WindowsFormsApplication1.Form2();
      return InternalForm2;
      // ----- Allow clearing, but not overwriting, of form.
      if (value == null)
        InternalForm2 = null;
        throw new Exception("That's a no-no.");

Now you can do the magic in C#:


A big downside to this code is that you must add it for every form included in your project. You could inject yourself into the Roslyn code generation process and emit the necessary partial MyForms class elements on a per-Form basis. Another option would be to use Reflection to scan through your assembly at runtime, looking for valid forms, and providing access to each one through an indexer or similar construct. But those sound like a lot of work. Don't those sound like a lot of work to you?

Of course, all of this begs the question as to whether this is the best way of invoking forms in a Windows Forms application. The traditional way of creating forms in C#, via as-needed instantiation, is probably the best way to manage form lifetimes in both C# and Visual Basic:

// ----- The best C# way...
(new WindowsFormsApplication1.Form2()).ShowDialog();

' ----- And its Visual Basic equivalent...
Call (New WindowsApplication1.Form2).ShowDialog()

But that's just code, not magic. And every program needs a little magic now and then.

About the Author

Tim Patrick has spent more than thirty years as a software architect and developer. His two most recent books on .NET development -- Start-to-Finish Visual C# 2015, and Start-to-Finish Visual Basic 2015 -- are available from He blogs regularly at

comments powered by Disqus


  • Uno Platform Ports Windows Calculator to Linux

    Uno Platform has ported the famed Windows Calculator, open sourced last year, to Linux as part of a continuing "proof point" effort to demonstrate the reach of what it describes as the sole UI offering available to target Windows, WebAssembly, iOS, macOS, Android and Linux with single-codebase applications coded in C# and XAML.

  • ASP.NET Core OData 8 Preview Supports .NET 5, but with Breaking Changes

    ASP.NET Core OData, which debuted in July 2018, is out in a v8.0 preview that for the first time supports the upcoming .NET 5 milestone release.

  • VS Code Java Team Details 5 Best Dev Practices

    Microsoft's Visual Studio Code team for Java development added a new Coding Pack for Java installer and detailed best practices for setting up a development environment.

  • Binary Classification Using PyTorch: Defining a Network

    Dr. James McCaffrey of Microsoft Research tackles how to define a network in the second of a series of four articles that present a complete end-to-end production-quality example of binary classification using a PyTorch neural network, including a full Python code sample and data files.

  • Blazor Debugging Boosted in .NET 5 RC 2

    In highlighting updates to ASP.NET Core in the just-launched second and final Release Candidate of .NET 5, Microsoft pointed out better debugging for Blazor, the red-hot project that allows for C# coding of web projects.

Upcoming Events