コード上で変更したFontの元FontのDispose

タグの編集
投稿者 バビ男  (社会人) 投稿日時 2017/7/13 10:17:08
こんにちは!
コード上でForm等のFontを変更するとき、例えば、

Me.Font = New Font(コンストラクタ引数)

のように書きますが、
元々のMe.Fontに入っていたFont情報ってDisposeすべきなのでしょうか?

Dim fOld As Font = Me.Font
Me.Font = New Font(コンストラクタ引数)
If fOld IsNot Nothing Then
    fOld.Dispose()
End If


ちなみに、VB2013です。
よろしくお願いします!
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/7/13 11:46:23
> 元々のMe.Fontに入っていたFont情報ってDisposeすべきなのでしょうか?

ご明察の通り、未使用となってどこからも参照されることが無い場合は、
即時に Dispose すべきです。

ただし Font や Image については注意が必要です。というのも、
  Dim f As New Font(.....)
  TextBox1.Font = f
  TextBox2.Font = f
のように、一つのインスタンスが複数のコントロールで共有されているケースがあるためです。

たとえば Panel や Form は、自身の上に別のコントロールを載せられますが、
この場合、子コントロールの Font プロパティの初期値は、
親コントロールの Font を引き継ぐことになっています。
※ このような動作のプロパティを、アンビエント(ambient)プロパティと言います。
https://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.font%28v=vs.90%29.aspx


具体例として、フォームに Label1 と Button1 を貼ってみます。プロパティは初期設定のままです。

1回目のクリックでは「親 Is 子:True」ですが、
2回目のクリックでは「親 Is 子:False」になるでしょう。

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim msg As String =
            "親 Is 子:" & CStr(Me.Font Is Me.Label1.Font) & vbCrLf &
            "親=子:" & CStr(Me.Font.ToString() = Me.Label1.Font.ToString()) & vbCrLf &
            "親:" & Me.Font.ToString() & vbCrLf &
            "子:" & Me.Label1.Font.ToString()
        MsgBox(msg)
        Me.Label1.Font = DirectCast(Me.Font.Clone(), Font)
    End Sub
End Class




アンビエントの状態を把握できない場合は、ガベージコレクトに任せるのも手ですが、
参照範囲を開発者がきちんと把握できている場合に限れば、、
どこからも使われてなくなったことが保証できる場合において、
明示的に Dispose するのが望ましいです。
投稿者 バビ男   (社会人) 投稿日時 2017/7/13 12:03:30
魔界の仮面弁士さま、いつもありがとうございます!
アンビエントプロパティについては注意します。
デザイナで、Formのフォントサイズを変更してから別のコントロールをFormに貼ると、
そのコントロールのFontのサイズがFormのそれと同じになってしまうのは
これが理由なのですね。

またまた勉強になりました!ありがとうございました! 
今後ともよろしくお願いします。