【VB.NET極致】動的コントロール制御の要:「AddressOf」と「AddHandler」を支配せよ
業務システム開発において、コントロールを動的に生成する設計は「諸刃の剣」です。
画面のグリッドにボタンを100個並べるような設計において、個別にクリックイベントを書くような非効率な実装は、今すぐ捨て去ってください。
今日は、VB.NETの真髄である「AddressOf」演算子と「AddHandler」を使いこなし、堅牢かつメモリリークとは無縁のイベント駆動設計を伝授します。
—
1. なぜ「AddressOf」が必要なのか?
初心者は「イベントハンドラは、デザイナー画面でダブルクリックして作るもの」と考えがちです。しかし、実行時に生成されるオブジェクトには、その特権はありません。
`AddressOf` は、「メソッドのメモリ上のアドレスを指し示す」演算子です。
イベントが発生した際、VB.NETのランタイムは「どのメソッドを実行すればいいのか?」をこのアドレスを通じて知るのです。
メモリを汚さないための原則
イベントを動的に紐付けるということは、「オブジェクトの生存期間」と「イベントの購読期間」を意識するということです。不用意に `AddHandler` を呼び続けると、オブジェクトが破棄されてもデリゲートが残り続け、メモリリークの温床となります。
—
2. 実践:動的生成とイベントハンドラの動的紐付け
以下のコードは、ボタンを動的に生成し、それらを一つのイベントハンドラで効率的に管理するプロフェッショナルな設計パターンです。
.net
”’
”’
Public Sub CreateDynamicButtons()
For i As Integer = 1 To 5
Dim btn As New Button With {
.Name = “btnDynamic_” & i,
.Text = “実行ボタン ” & i,
.Location = New Point(10, i 40)
}
‘ 【重要】AddHandlerでイベントを動的に紐付ける
‘ AddressOf [メソッド名] で、メソッドのアドレスを渡す
AddHandler btn.Click, AddressOf DynamicButton_Click
Me.Controls.Add(btn)
Next
End Sub
”’
”’
Private Sub DynamicButton_Click(sender As Object, e As EventArgs)
‘ senderをキャストして、どのボタンが押されたかを判定
Dim clickedBtn As Button = DirectCast(sender, Button)
‘ ここでDB連携やファイル操作を行う
MessageBox.Show($”{clickedBtn.Text} が押されました。処理を開始します。”)
End Sub
—
3. リークを防ぐ:RemoveHandlerの哲学
`AddHandler` を使ったなら、必ず終わりを意識してください。
特に、タブコントロールやユーザーコントロールを動的に破棄する設計の場合、`RemoveHandler` を呼ばないと、GC(ガベージコレクション)が回収できず、アプリは徐々に重くなります。
.net
‘ 破棄する直前に必ず解除する
Private Sub CleanupButtons(targetButton As Button)
‘ 紐付けを解除して参照を切る
RemoveHandler targetButton.Click, AddressOf DynamicButton_Click
targetButton.Dispose()
End Sub
—
4. 業務システム構築時の「鉄則」
現場のリーダーとして、以下の3点は徹底してください。
1. senderの検証を忘れない: `DirectCast` を使う際は、必ず `If TypeOf sender Is Button Then` のようなチェックを入れるか、例外処理を適切に実装すること。未知の型が紛れ込むことへの恐怖を持つ者が、堅牢なシステムを作れます。
2. ビジネスロジックとUIを分離する: `DynamicButton_Click` の中に直接複雑なSQLクエリを書くのはNGです。あくまでUIイベントのトリガーとし、実際のデータ処理は別のクラス(サービスクラス等)に委譲してください。
3. UIスレッドをブロックしない: イベント内で重いファイル処理やDB通信を行う場合は、`Async / Await` を併用し、画面がフリーズしない設計にすること。これがユーザーエクスペリエンス(UX)の差です。
—
最後に:コードは「読み手」のためにある
`AddressOf` を使った動的イベント制御は、コード行数を劇的に減らし、保守性を高めます。しかし、それは「なぜそう書いたのか」という設計思想がコードに残っていることが前提です。
あなたが書いたその `AddHandler` は、後任者が読んだときに「ああ、これはメモリリークを考慮してここで解除されているな」と納得できるものですか?
技術は道具に過ぎません。その道具を使って、「誰が保守しても壊れない仕組み」を構築することこそが、我々エンジニアの真の仕事です。さあ、今すぐあなたのコードを洗練させてください。
