My.Formsの謎に迫る
まず、VB.NET の WinForms プロジェクトを作成し、下記のようなコードを記述します。
(Form1 には、Button1 と Button2 の2つのボタンがあり、デザイナで Click イベントハンドラを設定しています)
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Test.HelloWorldA(Me)
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Test.HelloWorldB()
End Sub
End Class
Public Class Test
Public Shared Sub HelloWorldA(frm As Form1)
frm.Text = "Hello World! A"
End Sub
Public Shared Sub HelloWorldB()
Form1.Text = "Hello World! B"
End Sub
End Class
HelloWorldB メソッドでは Form1 のインスタンスを渡しておらず、何故かインスタンスが作成されていないForm1.Text プロパティに対して直接アクセスしてるように見えます。
一見コンパイルエラーになるように見えますが、奇妙な事に実際はこのコードはコンパイルエラーにもならないし、Button1 をクリックすると "Hello World! A"、Button2 をクリックすると "Hello World! B" にフォームのタイトルが切り替わります。
VisualStudioで、HelloWorldB の Form1 にマウスカーソルを当てると、下記のように表示されます。
ちなみに、ILSpy でC#にデコンパイルすると、下記のようになります。
WindowsApp1.My という名前空間と、その中に、My〇〇 というクラスが作成され、
MyProject クラスの中に Forms という静的プロパティがあり、その中に Form1 プロパティがあります。
C#の HelloWorldB メソッドのコードを見ると、
MyProject.Forms.Form1.Text = "Hello World! B";
となっています。VB.NET が勝手に My.MyProject.Forms にフォームのインスタンスを作成していて、
[フォームクラス名.プロパティ]
と記述すると、My.MyProject.Forms を省略し、そこにアクセスしたものと解釈してくれる訳ですね。まったく余計な事しやがって。
関連ドキュメントを漁ったら、下記のものが見つかりました。他にも色々な My オブジェクトがあるようですね。英語苦手な人は Google 翻訳通してください。
My.Forms Object
My.Internals: Examining the Visual Basic My Feature
Objects implicitly instantiated in vb.net?
My.Formsの問題点
VB.NET はデフォルトのプロジェクト設定だと Form から直接起動され、この場合は My.Forms のインスタンスが使用されますが、これをC#のように Main メソッドを作成し、プロジェクト設定のスタートアップオブジェクトを変更して、Main メソッドから起動してフォームを作成したとします。
Public Class Program
<STAThread>
Shared Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New Form1)
End Sub
End Class
これで Form1 の Button2 をクリックした場合どうなるかというと、フォームのタイトルは "Hello World! B" に設定されません。
Main メソッドで作成した Form1 と、MyProject.Forms.Form1 の Form1 のインスタンスは別物であり、現在画面に表示されているのは Main メソッドで作成した Form1 です。MyProject.Forms.Form1 の Text プロパティを更新した所で、当然フォームのタイトルは変わらないという訳ですね。
.NET開発の主流は C# で、VB.NET は開発も止まるみたいですし今後無くなっていくとは思いますが、既存の VB.NET のコードを C# に移植する際、My.Forms のような暗黙のオブジェクトはC#には無い要素なので、もし参照している箇所があったりするとハマりどころになる場合があるので注意が必要です。