tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルちょっと疑問
記事No10672
投稿日: 2012/02/01(Wed) 17:24
投稿者ふつうのこ
ちょっと疑問に思ったので質問します。
環境は、Windows2000, VB2005 です。

Form1, Form2 をつくり、Form2 にボタンのみを配置します。
以下がそのソースです。

Public Class Form1
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System. _
              EventArgs) Handles Me.Load
        Form2.Show()
    End Sub
End Class

Public Class Form2
    Public frmTarget As Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e _
                              As System.EventArgs) Handles Button1.Click
        Dim frmTemp As New Form1

        frmTemp.Text = "クローン"
        frmTemp.Show()

        frmTarget = frmTemp
        frmTemp.Dispose()
    End Sub
End Class

この時、frmTemp を frmTarget に代入しているに関わらず、Dispose されてしまいます。
ローカル変数はクラスレベル変数より強いですが…納得いきません。
バグですか?仕様ですか?

[ツリー表示へ]
タイトルRe: ちょっと疑問
記事No10673
投稿日: 2012/02/01(Wed) 17:37
投稿者Hongliang
Form1 は Class で定義されているので参照型になります。
参照型の代入式は、参照をコピーするという動作になります。
つまり、
frmTarget = frmTemp
とした場合、コピーされるのは参照だけであり、frmTarget も frmTemp も同じ一つの実体(インスタンス)を参照しているということです。
実体は一つなので、この時点で frmTarget.Dispose() と frmTemp.Dispose() は全く同じ意味になります。

[ツリー表示へ]
タイトルRe^2: ちょっと疑問
記事No10674
投稿日: 2012/02/01(Wed) 19:00
投稿者ふつうのこ
回答ありがとうございます。

全く同じ意味になるんですね。

では先のソースで frmTemp.Dispose 部をコメントアウトすると、クリックの度に
フォームが次々と出来ます。
当然 frmTarget が参照しているフォームも次々と変わる訳です。

参照が無くなったオブジェクトはガベージされると思いますが、参照が無くなってもこれらの
フォームは存在しています。
フォームはガベージされないのでしょうか?
また、Form1.Closed と Form1.Dispose は、イベントの発生以外は同じ意味ですか?

[ツリー表示へ]
タイトルRe^3: ちょっと疑問
記事No10676
投稿日: 2012/02/01(Wed) 19:45
投稿者Hongliang
> 参照が無くなったオブジェクトはガベージされると思いますが、参照が無くなってもこれらの
> フォームは存在しています。
> フォームはガベージされないのでしょうか?
表示中のFormは、閉じられるまでフレームワークが内部で参照を保持しています。
// Application.OpenFormsとかで取得できます。

> また、Form1.Closed と Form1.Dispose は、イベントの発生以外は同じ意味ですか?
基本的にDisposeの別名メソッドはDisposeと同等の動作をするのが推奨されますが、
Formの場合はたとえばShowDialogで開いたときのCloseなど、単純に破棄するメソッドではありません。
FormのDisposeを呼び出すのは、ShowDialogで表示したダイアログが閉じられた後ぐらいでしょう(それも実際には直接Disposeを呼び出すのではなくUsing構文で)。

[ツリー表示へ]
タイトルRe^4: ちょっと疑問
記事No10677
投稿日: 2012/02/02(Thu) 11:35
投稿者ふつうのこ
回答ありがとうございます。

ヘルプを見てみたのですが、MDIフォームで非表示の場合は Close で破棄されないとありました。

後、モードレスフォームで Close されると Show 出来ないと注意書きされていましたが、
モーダルフォームの Close については何も書かれていませんでした。

単純に破棄するのではない と書かれましたが、何が違うのでしょうか?

[ツリー表示へ]
タイトルRe^5: ちょっと疑問
記事No10678
投稿日: 2012/02/02(Thu) 14:43
投稿者魔界の仮面弁士
> 後、モードレスフォームで Close されると Show 出来ないと注意書きされていましたが、
> モーダルフォームの Close については何も書かれていませんでした。

モードレスフォームの Close は Dispose 処理を伴いますが、
モーダルフォームの Close は Dispose 処理を伴いません。
MSDN Library の ShowDialog メソッドの項も参照してみてください。


モードレスフォームとして呼び出した場合は、Show 後も呼び出し元の処理が
行われますよね。そのため、子フォームがいつ閉じられるのかを
呼び出し側では把握しにくいのです。このためモードレスフォームでは、
閉じられるタイミングで自動的に Dispose されるよう設計されています。


一方、モーダルフォームの場合は、Dispose の責は呼び出し元にあります。
もしも自動的に Dispsoe される仕様だとすると、画面が閉じた後では、
そのオブジェクトにアクセスできなくなるため、自動破棄では都合が悪いのです。

画面が閉じた後のアクセスというのは、たとえば OpenFileDialog クラスの動作を
思い出すとわかりやすいかも知れません(OpenFileDialog は Form ではないですが)。
OpenFileDialog クラスの場合、呼び出し側は ShowDialog した後、画面が
閉じられた後に、FileName プロパティなどを読み取る必要がありますよね。



ちなみに Form だけでなく、TextBox 等の Control についても、使用後には
Dispose が必要だったりします。ただし、フォームに貼り付けられている場合には、
親フォームが Dispose される際に、一緒に Dispose されるようになっているため、
通常はコントロールを意図的に Dispose する必要はありません。

[ツリー表示へ]
タイトルRe^6: ちょっと疑問
記事No10679
投稿日: 2012/02/02(Thu) 16:41
投稿者ふつうのこ
回答ありがとうございます。
大変よく分かりました。(*^^*)

前の質問の事なんですが、uctrlAns に Dictionary オブジェクトを格納する Dicプロパティを
設け、Dictionary オブジェクトに自フォームの uctrlAns の値を設定し、相手の uctrlAns の Dicプロパティに格納しています。

自フォームの表示を変える度に相手の Dicプロパティも次々に変わる訳で、前に入っていた
Dictionary オブジェクトを押し出して、新しい Dictionary オブジェクトが入ります。

押し出された物はガベージコレクタで掃除されるからいいかしら?って思っているのですが、
これも自分で破棄した方がいいでしょうか?

[ツリー表示へ]
タイトルRe^2: ちょっと疑問
記事No10675
投稿日: 2012/02/01(Wed) 19:04
投稿者ふつうのこ
Form1.Closed ではありませんでした。
Form1.Close です。(^^;)

[ツリー表示へ]