none
VB2008では、VB6の「Unload Me」に対応しているメソッドは? RRS feed

  • 質問

  • VB2008ユーザーと申します。

    素朴な質問です。
    以前までVB6を使用していたのですが
    VB2008に乗り換えのため変更ウィザードを使用したのですが
    VB6の「Unload Me」がVB2008では「Me.Close」になってます。
    けれども、動作としては「Unload Me」 <> 「Me.Close」のようなんですが
    これは正しいのでしょうか?

    検証として
    【VB6】
     Form1にCommand1とCommand2を作成
     From2にCommand1とTextBox1を作成

     Form1のコード
      Private Sub Command1_Click()
         Form2.Show 1
      End Sub
      Private Sub Command2_Click()
         Unload Me
      End Sub

     From2のコード
     Private Sub Command1_Click()
        Unload Me
     End Sub

    【VB2008】(補足:VB6で作成したプロジェクトを変換ウィザードで作成された結果です。)
     From1のコード
     Option Strict Off
     Option Explicit On
     Friend Class Form1
      Inherits System.Windows.Forms.Form
      Private Sub Command1_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command1.Click
         Form2.ShowDialog()
      End Sub
      Private Sub Command2_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command2.Click
        Me.Close()
      End Sub
     End Class

     Form2のコード
     Option Strict Off
     Option Explicit On
     Friend Class Form2
      Inherits System.Windows.Forms.Form
      Private Sub Command1_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command1.Click
       Me.Close()
      End Sub
     End Class

    検証動作として
     1、Form1からForm2を表示させます。
     2、Form2のテキストボックスに適当な文字列を入力します。
     3、入力後、Form2を閉じForm1に戻ります。
     4、再度、Form1からForm2を表示させます。

    結果として
     VB6では、2度目のForm2を表示させてもテキストボックスは空欄です。
     VB2008では、2度目のForm2を表示させると前回入力した内容がテキストボックスに残っています。

    皆さんはどうしていますか。

    私としましては、「Unload Me」と同等のメソッドが知りたいのですが、ご教授ください。
    また、Me.Closeはリソースを解放してくれないのでしょうか。

    よろしくお願いいたします。

    2009年6月24日 4:56

回答

  • MSDN ライブラリの Form.Close メソッドの解説によると、

     Form.Close メソッド (System.Windows.Forms)
     http://msdn.microsoft.com/ja-jp/library/system.windows.forms.form.close.aspx

     次の 2 つの条件が満たされている場合は、Close によってフォームが破棄されることはありません。
     1 つ目の条件は、フォームがマルチ ドキュメント インターフェイス (MDI: Multiple Document Interface) アプリケーションの一部として使用され、
     さらにそのフォームが非表示になっていること、2 つ目の条件は、ShowDialog を使用してフォームを表示していることです。
     これらの場合は、フォーム上のすべてのコントロールをガベージ コレクションの対象としてマークするために、Dispose を手動で呼び出す必要があります。

    とありますので、今回の元のソースですと ShowDialog でモーダル ダイアログを表示しているので、
    Me.Close の後で明示的に Me.Dispose を呼び出す必要があります。
    モーダル ダイアログの場合は、ShowDialog から戻ってきた後で Form にアクセスしたい場合がありがちなので、
    内部で自動的に Dispose を呼ばれて GC の対象としてマークされると、何かと具合が悪そうですから。
    2009年6月25日 1:36

すべての返信

  • あまりうまく説明はできませんが参考までに

    フォームを呼び出すとき

    From1のコード
     Option Strict Off
     Option Explicit On
     Friend Class Form1
      Inherits System.Windows.Forms.Form
      Private Sub Command1_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command1.Click
          
        Dim f As New Form2()
        
        f.Show()

      End Sub
      Private Sub Command2_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command2.Click
        Me.Dispose()
      End Sub
     End Class

     Form2のコード
     Option Strict Off
     Option Explicit On
     Friend Class Form2
      Inherits System.Windows.Forms.Form
      Private Sub Command1_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command1.Click
       
          Me.Dispose()

      
    End Sub
     End Class

    .NETになってからはVB6の時とはまったく考え方が違います・・・。

    すべてはクラスとして考えられています。

    クラスは必ずインスタンスして(Newというキーワード)使用します。


    またリソースもガベージコレクターというものが管理をしていて
    プログラマは例外を除き明示的にメモリの解放ができません、
    そのかわりガベージコレクターが勝手にメモリ管理を行ってくれます。

    http://homepage1.nifty.com/rucio/main/main.htm

    こちらのサイトの方がVB.NETについて詳しく丁寧に解説されていますので
    一度呼んでみたらいかがでしょうか?

    2009年6月24日 9:57
  • またリソースもガベージコレクターというものが管理をしていて
    プログラマは例外を除き明示的にメモリの解放ができません、
    そのかわりガベージコレクターが勝手にメモリ管理を行ってくれます。
    (「リソース」の指す意味によるのかもしれませんが、)通常、ガベージコレクタは「リソース」を管理しません。
    従って、リソースを作成・確保するクラスは、そのリソースを解放する手段としてDisposeメソッドを実装したり、保険としてファイナライザを実装することになります。



    VB.NETでは「既定のインスタンス」というものがあるので分かりにくいのかもしれません。
    さとさと1さんのサンプルコードのように、自分でNewして、その変数に対してShowメソッドを実行するように作り替えると起きている現象は解決できると思います。
    # 個人的にはいきなりDisposeではなく、Closeで閉じた方が良いと思う...
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年6月24日 14:06
    モデレータ
  • さとさと1さん
    Azuleanさん

    回答ありがとうございます。

    フォームを呼び出すときには、インスタンスを行わないといけないのですね。

    Newしてフォームを表示したことで、テキストボックスが初期状態となりました。


    ここでまた疑問が発生しました。

    フォームを閉じるとき、「Me.Close」だけではリソースは解放されないのでしょうか。

    フォームを閉じるときにリソースを解放したい場合は、下記のようにしても良いのでしょうか。

     'フォームを閉じる
     Me.Close
     'リソースを解放する
     Me.Dispose


    ご回答お願いいたします。

    2009年6月25日 0:32
  • MSDN ライブラリの Form.Close メソッドの解説によると、

     Form.Close メソッド (System.Windows.Forms)
     http://msdn.microsoft.com/ja-jp/library/system.windows.forms.form.close.aspx

     次の 2 つの条件が満たされている場合は、Close によってフォームが破棄されることはありません。
     1 つ目の条件は、フォームがマルチ ドキュメント インターフェイス (MDI: Multiple Document Interface) アプリケーションの一部として使用され、
     さらにそのフォームが非表示になっていること、2 つ目の条件は、ShowDialog を使用してフォームを表示していることです。
     これらの場合は、フォーム上のすべてのコントロールをガベージ コレクションの対象としてマークするために、Dispose を手動で呼び出す必要があります。

    とありますので、今回の元のソースですと ShowDialog でモーダル ダイアログを表示しているので、
    Me.Close の後で明示的に Me.Dispose を呼び出す必要があります。
    モーダル ダイアログの場合は、ShowDialog から戻ってきた後で Form にアクセスしたい場合がありがちなので、
    内部で自動的に Dispose を呼ばれて GC の対象としてマークされると、何かと具合が悪そうですから。
    2009年6月25日 1:36
  • totojoさん

    返信遅くなりました。

    ガベージコレクションを確認しました。
    VB6からの移行は厄介ですね。

    ShowDialogで呼び出したFormは
    Me.Close
    Me.Dispose
    で閉じるようにします。
    2009年6月29日 7:39