none
Formの継承にてのShowイベントにてNullReferenceException RRS feed

  • 質問

  • お世話になっております。

    VB2008.NetにてForm1を継承して、

    Form2とForm3を作成しております。

    Form2をスタートアップフォームに登録しており

    実行するとForm2から立ち上がりますが

    Form3からForm2のFormを閉じようとすると、NullReferenceExceptionが出ます。

    Form2のインスタンスはForm2のロードイベントで

    f2=Me としているので、ないはずはないと考えております。

    どうして例外が発生するのか分かりません。

    ちなみに張り付けたコードの①のように変えると問題なく動くのですが

    Form2はダブってインスタンス作成されているような気がしています。

    これで正解なのか、ご教示ください。

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

    Public Class Form1
    
    
        Friend f2 As Form2
        Friend f3 As Form3
    
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
            'f2 = New Form2 '①←コメント削除
    
            f3 = New Form3
    
        End Sub
    End Class
    
    Public Class Form2
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            f3.Show() ' ⇒NullReferenceExceptionが出る
            f2.Hide()
    
        End Sub
    
        Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
            f2 = Me ' ①コメントアウト
    
        End Sub
    
    End Class
    
    Public Class Form3
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            f2.Show() 'NullReferenceException
    
            f3.Hide()
    
        End Sub
    End Class
    

    2017年1月16日 1:03

回答

  • やるとするなら、たとえばForm3のコンストラクタではForm2を引数で受け取るようにして、自分のf2にセットするようにするか、もしくは、

     f3 = New Form3

     f3 = New Form
     f3.f2 = Me

    などとするか、ですかね(本当はプロパティにした方がいいですが)。

    そもそもf2やf3はForm1に持たせるのではなくて、Form2がf3を、Form3がf2を個別に持つ方が多分良いでしょう(今の使い方なら、ですが)。

    Form2やForm3が自分自身を操作する場合は、f2やf3ではなくMeを使う方がいいです。

    その方が何をやっているのか明確になります(今の使い方だとインスタンスの関係がわけがわからなくなります)。



    • 編集済み なちゃ 2017年1月16日 1:23
    • 回答としてマーク to1109 2017年1月16日 2:10
    2017年1月16日 1:15

すべての返信

  • インスタンスおよびインスタンスの変数の関係がきちんと把握できていないようですので、この状態だとちょっと厳しいかも。

    簡単に言うとf2、f3という変数はForm2、Form3それぞれが自分自身専用で持っている状態になりますので、こういう使い方はできません。

    ※Form2のインスタンスが持っているf2、f3、Form3インスタンスが持っているf2、f3が個別にある

    もちろんそれぞれインスタンス変数ですので、当然Form2やForm3をNewするたびにそれぞれ専用の変数ができるイメージになります。


    • 編集済み なちゃ 2017年1月16日 1:17
    2017年1月16日 1:10
  • やるとするなら、たとえばForm3のコンストラクタではForm2を引数で受け取るようにして、自分のf2にセットするようにするか、もしくは、

     f3 = New Form3

     f3 = New Form
     f3.f2 = Me

    などとするか、ですかね(本当はプロパティにした方がいいですが)。

    そもそもf2やf3はForm1に持たせるのではなくて、Form2がf3を、Form3がf2を個別に持つ方が多分良いでしょう(今の使い方なら、ですが)。

    Form2やForm3が自分自身を操作する場合は、f2やf3ではなくMeを使う方がいいです。

    その方が何をやっているのか明確になります(今の使い方だとインスタンスの関係がわけがわからなくなります)。



    • 編集済み なちゃ 2017年1月16日 1:23
    • 回答としてマーク to1109 2017年1月16日 2:10
    2017年1月16日 1:15
  • あー、そうですね。回答ありがとうございます。

    目が覚めた気分です。

    分かりました。再検討します。

    Form1に変数準備したんで共通でだいじょうぶと勘違いしておりました。。。

    Form1自体が、Form2、Form3に存在してますね。。。

    どうしよ。。

    2017年1月16日 1:18
  • 回答が入れ違いになってしまいました。

    分かりました。ですが、本当は、Formは10個くらいになる予定ですので

    ちょっとややこしい気がします。

    まだ、してみてないので何とも言えない素人なのですが

    Form1でSharedでf2,f3を宣言すると、とりあえずは回避できますよね。。

    でも、、本来の目的では、Form1は共通処理を書く予定なので

    根本的に間違っておりました。。

    2017年1月16日 1:28
  • 回答ありがとうございました。

    再検討しました。

    なっちゃん様の言われるように、インスタンスを渡す方法にしました。

    今回は、Form1、Form2、Form3より、さらに、大本で管理するための

    MainFormを作成して、Form2、Form3のインスタンス作成時にMainFormの

    インスタンスをコンストラクタの引数で渡すようにしました。

    ありがとうございました。

    危うく、変な挙動のソフトを作るところでした。。

    2017年1月16日 2:10