tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^5: Penの操作でエラー(VBS2005)
投稿日: 2008/05/23(Fri) 11:39
投稿者よねKEN
> > しかし、Dispose メソッド(正確には、IDisposable インターフェイス)を有する
> > クラスの場合だけは例外です。IDisposable なクラスの場合には、処理の最後に
> > Dispose を呼び出して、使い終わった内部リソースを破棄せねばなりません。
> > (この処理を自動的にやってくれるのが、Using ステートメントです)
> Disposeメソッドがあるものは 必須ということですね。分かりました。
> (Usingはこれから見てみます)

Disposeメソッドを持つクラスで自分の管理下にあるインスタンスについてのみ
Disposeメソッドを発行した方がよい、です。

例えば、あるメソッドでNewしたPenのインスタンスでそのメソッドの中でしか
使用しないものであれば、そのメソッド内でDisposeするべきでしょう。
しかし、他のところから渡されたPenはDisposeすべきでしょうか、
するべきではないでしょうか。この判断は難しい場合もありますが、
誰がDisposeすべきか?を考えておくとよいです。

> PenをDisposeするタイミングですが、次のようにしてみました。(省略して記載)
> ただ、これでいいのか?かなり不安なのです。アドバイスをお願いします。
>
> Public Class ShapeDraw
>     Public Circle As New clsCircle
>     Public Circles As New List(Of clsCircle)
>
>     Public Sub AddCircles(ByVal 中心x As Single, ByVal 中心y As Single, ByVal 半径 As Single, ByVal 始点角 As Single, ByVal 終点角 As Single, ByVal pen As Pen)
>         Dim mCircle As New clsCircle
>         With mCircle
>             .pen = pen.Clone
>         End With
>         Circles.Add(mCircle)
>     End Sub
>
> Public Class clsCircle
>     Public pen As New Pen(Color.Black, 1)
>  
>     Public Function Turn(ByVal Angle As Single) As clsCircle
>         Dim dum As New clsCircle
>         dum.pen = pen.Clone

dum.penが持つ元々のインスタンスのDisposeが呼ばれていません。

>         pen.Dispose()'ここでclsCircleのpenを破棄

ここでpenをDisposeすると次にこのインスタンスのTurnメソッドを呼び出すときに
例外が起きるので問題があると思います。

>         Return dum'ここではdum.penの破棄は行えないはず
>     End Function

penはインスタンス変数ですので、このpenのDisposeを呼ぶタイミングは、
clsCircleクラスのインスタンスが破棄されるタイミングになるかと思います。
この点を厳密にやろうとすると、clsCircleクラス自身も
IDisposableインターフェースを実装し、Disposeメソッドを用意する。
そして、ObjectのFinalizeメソッドをオーバーライドする必要があります。

またpenフィールドは外部から設定できるようになっていますが、
設定不要であれば、ReadOnlyにしておいた方がよいと思います。
外部からpenに新たなインスタンスを設定する場合、
それまでに持っていたインスタンスのDiposeが呼ばれません。
#penフィールドにセットする側がセットする前に古いインスタンスの
#Disposeを実行する責任を持つのであれば問題ありません。

>
> Public Class Form1
>     Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
>         Dim pen As New Pen(Color.Black, 1)
>         pen.Width = 1
>         pen.Color = Color.Black
>         pen.DashStyle = Drawing2D.DashStyle.Solid
>         With Me.ShapeDraw1
>             pen.Color = Color.Red
>             pen.DashPattern = New Single() {10.0F, 2.0F, 2.0F, 2.0F, 2.0F, 2.0F, 2.0F}
>             .AddCircles(100, 100, 50, 90, 360, pen)
>
>             pen.Color = Color.Green
>             pen.DashStyle = Drawing2D.DashStyle.Solid
>             .AddCircles(200, 200, 50, pen)
>             .Refresh()
>         End With
>         pen.Dispose()'ここでPenの破棄

こちらはOKです。

>     '.AddCirclesでShapeDrawのCircles As New List(Of clsCircle)に保存されたPenも破棄しなければいけないのだろうか?

この点は、先ほど指摘したようにclsCircleがIDiposableを実装する場合、
clsCircleのインスタンスが不要になったら、clsCircleのDisposeメソッドを
呼ぶようにすることで解決します。

>     End Sub
> End Class


上記で指摘した内容はそれなりにややこしいと思います。
そこでもう一つの案なのですが、clsCircleはPenクラスのインスタンスを持つ必要があるでしょうか?という点です。
Penが必要になるのは描画するときですから、clsCircleにPenを保持する必要はなく、
描画するときにPenインスタンスを作って、描画の作業が終わったら即座にPenインスタンスを破棄すればよいです。

clsCircleを描画するのにたぶん色情報と線の太さが必要だろうと思いますが、
この情報だけをclsCircleが持てばよいのではないでしょうか。

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。