私は過去2年間にわたってExcel VBAを教えてきましたが、コードセグメントの最後で変数を破棄することが適切な場合があるという考えがあります。たとえば、 Ron de BruinがExcelをHTMLに転送するためのコード :
Function SaveContentToHTML (Rng as Range)
Dim FileForHTMLStorage As Object
Dim TextStreamOfHTML As Object
Dim TemporaryFileLocation As String
Dim TemporaryWorkbook As Workbook
...
TemporaryWorkbook.Close savechanges:=False
Kill TemporaryFileLocation
Set TextStreamOfHTML = Nothing
Set FileForHTMLStorage = Nothing
Set TemporaryWorkbook = Nothing
End Function
私はこれをいくつか検索しましたが、それを行う方法を超えてほとんど何も見つかりませんでした、そして1つのフォーラムの投稿で ローカル変数をクリアする必要がないというステートメント 、それらはEnd Sub
。上記のコードに基づいて、End Function
、または他の状況では遭遇していません。
だから私の質問はこれに要約します:
そして、ここで誰かが説明できない場合は...
VB6/VBAは、決定論的アプローチを使用してオブジェクトを破棄します。各オブジェクトには、それ自体への参照の数が格納されます。数がゼロに達すると、オブジェクトは破棄されます。
オブジェクト変数は、スコープから外れたときにクリーンアップ(Nothing
に設定)されることが保証されています。これにより、それぞれのオブジェクトの参照カウンターが減少します。手動による対策は不要です。
明示的なクリーンアップが必要な場合は2つだけです。
変数がスコープ外になる前にオブジェクトを破棄したい場合(たとえば、プロシージャの実行に時間がかかり、オブジェクトがリソースを保持しているため、できるだけ早くオブジェクトを破棄して、資源)。
2つ以上のオブジェクト間に循環参照がある場合。
objectA
がobjectB
への参照を保存し、objectB
がobjectA
への参照を保存する場合、明示的にチェーンを解除しない限り、2つのオブジェクトは破棄されません。設定objectA.ReferenceToB = Nothing
または objectB.ReferenceToA = Nothing
。
表示するコードスニペットが間違っています。手動でクリーンアップする必要はありません。 より正確なコードの誤った感覚 が得られるため、手動でクリーンアップすることは有害です。
クラスレベルで変数を使用している場合、クラスインスタンスが破棄されると、変数は消去/破棄されます。必要に応じて、より早く破棄できます(アイテム1.
)。
モジュールレベルで変数を使用している場合、プログラムが終了すると(または、VBAの場合はVBAプロジェクトがリセットされると)、変数は消去/破棄されます。必要に応じて、より早く破棄できます(アイテム1.
)。
変数のアクセスレベル(パブリック対プライベート)は、そのライフタイムに影響しません。
VBAは、 参照カウント で実装されるガベージコレクターを使用します。
特定のオブジェクトへの複数の参照が存在する場合があります(たとえば、Dim aw = ActiveWorkbook
は、アクティブなワークブックへの新しい参照を作成します)。したがって、ガベージコレクターは、他の参照がないことが明らかな場合にのみオブジェクトをクリーンアップします。 Nothingに設定することは、参照カウントを減少させる明示的な方法です。スコープを終了すると、カウントは暗黙的に減らされます。
厳密に言えば、最新のExcelバージョン(2010以降)ではNothingに設定する必要はありませんが、古いバージョンのExcelには問題がありました(回避策は明示的に設定することでした)
データが自動的にクリーンアップされず、最終的に「メモリ不足」エラーが発生する状況が少なくとも1つあります。私が持っていたユーザーフォームで:
Public mainPicture As StdPicture
...
mainPicture = LoadPicture(PAGE_FILE)
UserFormが破棄されたとき(Unload Me
)mainPicture
にロードされたデータに割り当てられたメモリは、割り当て解除されていませんでした。明示的に追加する必要がありました
mainPicture = Nothing
終了イベントで。