none
破棄されたオブジェクトかどうかの判断 RRS feed

  • 質問

  • Form ParentForm から、子フォームであるChildForm を
    Show()メソッドで開きます。

            private ChildForm form;

            private void showChildButton_Click(object sender, EventArgs e)
            {
                if (form == null)
                    form = new ChildForm();
                form.Show();
            }

    この、
    if (form == null)
    というのが、曲者なのですが、
    最初にChildForm をShow()メソッドで開くときには、
    (form == null)
    なので、
    form = new ChildForm();
    で、無事ChildFormが開きますが、
    開いたChildForm をいったん閉じたうえで、もう一度
    if (form == null)
    とすると、ChildForm であるform(インスタンスというのでしょうか?) は既にnullでないため。
    form.Show();
    のところで、「破棄したオブジェクトにアクセスできません」というエラーとなってしまいます。
    なので、
    (form == null)
    というのは、form が破棄されたかどうかの判断としては利用できないということだろうと思います。

    という訳で、ChildForm が破棄されたかどうか(閉じるボタンで閉じたか)を判断するにはどうしたらよいのでしょうか?

    どうぞ、よろしくお願いいたします。
    2010年3月9日 13:09

回答

  • Dispose メソッドによる明示的な破棄とガベージコレクタによる回収は違うものです。

    Dispose メソッドはそのインスタンスが保持しているアンマネージリソースを解放する役割を持つことが多くなっています。
    アンマネージリソースが解放された後でも、マネージのインスタンス自体は残っていますので、form 変数で使われている限り、ガベージコレクタによって回収されることはありません。

    このため、一度でも ChildForm のインスタンスが代入された form 変数が null になることはありません。
    (ご自身で null を代入した場合を除く)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年3月9日 14:23
    モデレータ
  • 今問題とされていることだけを直接的に解決するのであれば、IsDisposed プロパティを利用したら良さそうに見えます。
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.isdisposed.aspx


    なお、Dispose メソッドを持つクラスのすべてが IsDisposed プロパティを持っているわけではありません。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク yasheeki 2010年3月9日 13:50
    • 回答としてマークされていない yasheeki 2010年3月9日 13:50
    • 回答としてマーク yasheeki 2010年3月9日 13:50
    • 回答としてマークされていない yasheeki 2010年3月9日 13:55
    • 回答としてマーク 高橋 春樹 2010年3月15日 5:53
    2010年3月9日 13:33
    モデレータ
  • 「Dispose(破棄)されているか」と「ガベージされているか」と「参照がnullになっているか」は同列にできません。3つは全く別の概念です。

    インスタンスがDisposesされていても参照が残っている場合、いつまで経ってもガベージされませんし、今回の例ではformがnullになっていてもガベージされたとは限りません。

    • 回答としてマーク yasheeki 2010年3月11日 14:44
    2010年3月9日 14:27

すべての返信

  • 今問題とされていることだけを直接的に解決するのであれば、IsDisposed プロパティを利用したら良さそうに見えます。
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.isdisposed.aspx


    なお、Dispose メソッドを持つクラスのすべてが IsDisposed プロパティを持っているわけではありません。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク yasheeki 2010年3月9日 13:50
    • 回答としてマークされていない yasheeki 2010年3月9日 13:50
    • 回答としてマーク yasheeki 2010年3月9日 13:50
    • 回答としてマークされていない yasheeki 2010年3月9日 13:55
    • 回答としてマーク 高橋 春樹 2010年3月15日 5:53
    2010年3月9日 13:33
    モデレータ
  • ありがとうございます。

        if (form == null)
            form = new ChildForm();
        else if (form.IsDisposed)
            form = new ChildForm();
        form.Show();
    とすることで、解決しました。

    ただ、破棄されているのにnull ではないということは、ガーベージコレクタ(というのでしょうか?)が
    まだ、処理を終えていない段階だということですよね?

    ChildForm を閉じて10分しても、form はnull になりませんでしたが、
    それは、関係ないことなのでしょうか?
    2010年3月9日 13:55
  • Dispose メソッドによる明示的な破棄とガベージコレクタによる回収は違うものです。

    Dispose メソッドはそのインスタンスが保持しているアンマネージリソースを解放する役割を持つことが多くなっています。
    アンマネージリソースが解放された後でも、マネージのインスタンス自体は残っていますので、form 変数で使われている限り、ガベージコレクタによって回収されることはありません。

    このため、一度でも ChildForm のインスタンスが代入された form 変数が null になることはありません。
    (ご自身で null を代入した場合を除く)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年3月9日 14:23
    モデレータ
  • 「Dispose(破棄)されているか」と「ガベージされているか」と「参照がnullになっているか」は同列にできません。3つは全く別の概念です。

    インスタンスがDisposesされていても参照が残っている場合、いつまで経ってもガベージされませんし、今回の例ではformがnullになっていてもガベージされたとは限りません。

    • 回答としてマーク yasheeki 2010年3月11日 14:44
    2010年3月9日 14:27
  • ご指導ありがとうございます。

    ・Dispose(破棄)されているか
    ・ガベージされているか
    ・参照がnullになっているか

    この3つの概念を区別したいと思います。
    (割合難しいことなのでしょうか?)
    2010年3月9日 14:41
  • この3つの概念を区別したいと思います。
    (割合難しいことなのでしょうか?)
    「難しい」というのは主観によります。
    私が「簡単だ」と言っても、受け手によって抱く感想は違いますよね。

    ただ、これらを明確に区別し、どのようなものかを理解していないと、今後、不具合を招くことになると思います。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年3月9日 14:59
    モデレータ
  • ありがとうございます。

    きっと、私には難しそうですが、基礎として必要なレベルの問題だろうと思います。
    テイストなどを読み返して勉強してみます。
    2010年3月11日 11:28