NullReferenceException について
初級者向けにおさらいします。
目次
この例外エラーの説明
Null Reference(参照しようとした変数が null 状態、つまり Nothing 状態(準備できていない状態)なのに使おうとアクセスすることで発生する)Exception です。
事例とその対処方法
例外エラーは、想定外の扱われ方をすると発生して飛んで来ます。それは命令の使い方が間違っていたり、存在しないデータを扱おうとしていたり、アカウント権限を越えたアクセスをしようとしていたり(Windows 側やウェブ側の話だったり)、サービスが動いていないのに連携しようとしたり、製品上の仕様考慮モレだったり、そういう系です。
こうなっている前提のはずだから、こうやろうとしたのに、実際はここがこうなっているからダメじゃん!こういう場合の処理が無いじゃん!みたいなコードになっていませんか?
クラス型データ全般
実際には、以下のような使い方はあまりないかと思います。
Class Class1 Public Number As Integer = 0 End Class Module Module1 Sub Main() Dim obj As Class1 = Nothing Dim number As Integer = obj.Number Console.ReadKey() End Sub End Module
System.NullReferenceException: 'オブジェクト参照がオブジェクト インスタンスに設定されていません。' obj が Nothing でした。
以下のように、メソッドに渡した引数がインスタンス生成されていなかった、またはそのメンバーがインスタンス生成されていなかった、というケースの方が多いかもしれません。
Sub Main() Dim obj As Class1 = Nothing Work(obj) Console.ReadKey() End Sub Sub Work(obj As Class1) Dim number As Integer = obj.Number End Sub
対策としては、事前にインスタンスチェックすることですが、できるだけインスタンスチェックしなくてもインスタンス生成されていることが保証できるような書き方を目指した方が良い気がします。
Sub Work(obj As Class1) ' 1 If obj IsNot Nothing Then Dim number As Integer = obj.Number End If ' 2 Dim number2 As Integer? = obj?.Number ' obj is Nothing -> number2 = Nothing ' -> number2 = Integer Value If number2.HasValue Then End If ' 3 Dim number3 As Integer = If(obj Is Nothing, 0, obj.Number) End Sub
例えば、限定的であまり良い例ではないですが、インスタンス生成してから渡している場合、あえて Work メソッド内でインスタンスチェックする必要はないと思います。
Sub Main() Dim obj As Class1 = New Class1 Work(obj) Console.ReadKey() End Sub Private Sub Work(obj As Class1) Dim number As Integer = obj.Number End Sub
あとは、できるだけクラス型データの場合は、デフォルトで宣言と同時に初期化(インスタンス生成)しておくことです。