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

「オブジェクト参照がオブジェクト インスタンスに設定されていません。」は誰でも一度は目にしたことがあるはずの例外である。原因は、インスタンス化されていない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

関連情報

・Microsoft JScript 実行時エラー:オブジェクトを指定してください。
・このログインで要求されたデータベースXXX を開けません。ログインに失敗しました。ASPNET はログインできません
・Logging Application Blockのトラブルシューティング
・IISのログ出力先
・このログインで要求されたデータベースXXX を開けません。ログインに失敗しました。ASPNET はログインできません
・C# 3.5 yieldの読み方
・ASP.NET サーバーサイドのイベント処理の順番
・ASP.NETのWebページでグーグルアドセンスを貼り付ける方法
・IIS メタベースにアクセスできませんでした
・VSSで管理されているプロジェクトは、ファイルの名前の変更や移動は極力行わない方が良い
・Oracle 9.2へOLE DB接続する方法
・単体テストのデータ
・この行は既に別のテーブルに属しています
・データベースのバージョンは 655 なので、開けません。
・証明書ストアでマニフェスト署名用の証明書が見つかりません。
・次のモジュールは最適化を有効にされて、またはデバッグ情報なしでビルドされました
・String.Concatメソッドを使った文字列の連結
・ファイルの存在をチェックする
・テキストファイルをロードし文字列を読み込むサンプル
・任意の数の引数を受け取るメソッド

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