累計
本日
昨日

「オブジェクト参照がオブジェクト インスタンスに設定されていません。」を設計で防ぐ

「オブジェクト参照がオブジェクト インスタンスに設定されていません。」は誰でも一度は目にしたことがあるはずの例外である。原因は、インスタンス化されていないNothingl(Null)のオブジェクトを参照したために発生したものである。この記事では、この例外が発生しないようにするコーディングおよび設計上のテクニックをまとめた。

まず、例外が発生するサンプルを下記に示す。Personクラスはnameをメンバ変数にもつクラスである。


このPerosnクラスのインスタンスを生成し、プロパティNAMEの文字数を取得しようとすると、Nameの実体である_nameが初期化されていないので、2行目で異常終了(=アベンド=クラッシュ=落ちる)してしまう。これは、_nameがインスタンス化されていないNothing(null)のオブジェクトであるためである。

回避するには、次のような方法がある。
  1. データをチェックする
  2. Try~Catch句で例外を捕捉する
  3. 例外が起こらないクラス設計にする
1は例外が起こる前にチェックする方法である。Nothing(Null)の場合はメッセージを表示する。簡単であるが、チェックするものが多いとコードの可読性が悪くなってしまう。

2はTry~Catch句を使って、例外が発生した場合の処理を埋め込んでおく方法である。1の場合は、チェックする項目が多いとコードが煩雑になるが、どんな例外が発生してもメッセージを表示することができる。ただ、このようなTry~Catch句を分岐処理の代わりに使うプログラミングは望ましくないと筆者は考える。例外は予期せぬ事態が発生したときの処理だけにすべきと考える。

3は1,2と違い利用される側Personクラスに細工を施し、例外を発生させないようにする方法である。1,2はチェックやTry~Catch句のためコードの可読性が悪い。もし、PersonクラスのNameがNothing(null)にならないのであれば、次のように利用する側のコードは単純にできる。
Personクラスの細工は次のように、引数のあるコンストラクタを追加し、デフォルトコンストラクタ(引数のないコンストラクタ)の場合でも、メンバ変数を初期化するようにする。下記のサンプルでは、デフォルトコンストラクタが呼ばれたとき、引数ありのコンストラクタを呼びだし、メンバ変数を初期化している。初期化にはプロパティを使用しNothing(null)の場合は””を代入している。また、コードをシンプルにするためC#のみ3項演算子を使用した。

トラックバック

トラックバックURL:
http://www.apricot-jp.com/cgi/mt/mt-tb.cgi/293

関連情報

Copyright(C) 2007 アーキテクト360 Allrights reserved.