VB.NETでは、動的にコントロールを作成するために、必要なクラスのインスタンスを作成し、それをControlsコレクションに追加します。動的に作成されたコントロールのイベントを処理するために、VB.NETではデリゲートとAddHandler演算子を使用します。
例(VB.NET):
Dim btn As New Button() btn.Text = "クリックしてください!" btn.Location = New Point(40, 40) Me.Controls.Add(btn) AddHandler btn.Click, AddressOf Button_Click Private Sub Button_Click(sender As Object, e As EventArgs) MessageBox.Show("動的に作成されたボタンがクリックされました。") End Sub
従来のVB6では、動的にコントロールを作成してイベントを処理するために、コントロール配列(Control Arrays)を通じてのみ可能であり、インデックスで各要素を区別します。
例(VB6):
' フォーム上にはIndex = 0のCommandButtonが必要です Load Command1(1) Command1(1).Visible = True Private Sub Command1_Click(Index As Integer) MsgBox "インデックス" & Index & "のボタンが押されました!" End Sub
VB.NETにはVB6のようなコントロール配列の概念はなく、動的に作成されたコントロールのイベント処理はデリゲートとAddHandler/RemoveHandlerメカニズムのみによって行われます。
質問: "動的に作成されたコントロールの削除時にRemoveHandlerを忘れるとどうなるか?それにはどんな影響がありますか?"
回答: コントロールを削除する前にRemoveHandlerを呼び出すのを忘れると、ハンドラへの参照がメモリに残り、メモリリーク(memory leak)が発生し、時には既に削除されたオブジェクトやフォームにアクセスしようとするため、例外が発生する可能性があります。
例:
' 忘れたRemoveHandler: ' AddHandler btn.Click, AddressOf SomeHandler ' Controls.Remove(btn) ' btnはもうないが、ハンドラが残っている
物語
決済ターミナル用のビリングシステムで、支払い操作用のダイナミックボタンがパネルに作成されました。ウィンドウを閉じた後、残ったイベントハンドラがガーベジコレクションを妨げました。1週間でアプリはメモリリークを引き起こし、サーバーがダウンする原因となり、夜間運用の上でプロセスを手動で再起動する必要がありました。
物語
WinFormsでの医療ビジュアライゼーションプロジェクトで、多くの"画像プレビュー"を生成するためにPictureBoxが作成され、削除されました。開発者はイベントハンドラを削除しませんでした。アプリケーションの20-30回の読み込み後、遅くなり始めました。隠れたハンドラが何千も残り、リソースの解放を妨げていたことがわかりました。
物語
子供向けの教育アプリの1つで、クイズのボタンが動的に形成され、ゲーム終了後にフォームから削除されましたが、RemoveHandlerを通じてイベントは解除されませんでした。そのため、新しいゲームが開始される際に"幽霊"のコードチェックが発生し、古いポップアップやポイントのバグ、全体的な混乱が引き起こされました。