2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[VB.NET] 暗黙のFormオブジェクト~My.Forms

Last updated at Posted at 2020-09-16

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 にマウスカーソルを当てると、下記のように表示されます。
VisualStudio表示

ちなみに、ILSpy でC#にデコンパイルすると、下記のようになります。
decomp.jpg

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#には無い要素なので、もし参照している箇所があったりするとハマりどころになる場合があるので注意が必要です。

2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?