2010-11-21 10 views
2

私は現在、それはで「MyMethodは」により使用される前に、参照がnullであるかどうかを確認しようとしている。しかし、私は」C#の - 「オブジェクト参照オブジェクトのインスタンスに設定されていない」

if (School.ClassRoom.Pupil.Age != null) 
     { 
      MyMethod(School.ClassRoom.Pupil.Age); 
     } 

最初の行で "オブジェクトのインスタンスに設定されていないオブジェクト参照"が残っていますが、Ageがnullであるだけでなく、PupilとClassRoomもnullになることがあるためです。

Tryのコードで同じエラーが発生するため、Try、Catch、Finallyを使用して同じ問題が発生しています。

このメソッドを使用するたびに、各ClassRoomでnullを確認し、次に各瞳孔をnullに、各Ageをnullにする必要はありません。

これを行う簡単な方法はありますか?

+0

School.ClassRoom ..のデータはどのように記入しますか?充填している間、NULL行は解決策ではないでしょうか? –

+0

Btw、あなたのタイトルは適切ではないようです。あなたが得ている例外について混乱することはありません。 –

+0

可能であれば、これは非常に複雑なデータ構造の一部であり、すべてのnullの新しいインスタンスを作成し始めると、メモリ使用量が屋根を通過すると考えられるので、nullクラスを使用し続けることができるようにしたいと考えています。 – Caustix

答えて

5

Groovyのnull安全な参照解除演算子のようなものですが、if (School?.ClassRoom?.Pupil?.Age != null)と書くことができますが、C#にはそのようなことはありません。

私はそれが nullになることができますと仮定して、あなたがNULLかどうかのために各プロパティをチェックするを持っている怖い:もちろん

if (School != null && School.ClassRoom != null && School.ClassRoom.Pupil != null 
    && School.ClassRoom.Pupil.Age != null) 
{ 
    MyMethod(School.ClassRoom.Pupil.Age); 
} 

、あなたがメソッドの呼び出し自体を含むこの全体のifブロックを置くことができますヘルパーメソッドを呼び出し、それを呼び出します。

これは、各プロパティがの場合に有効であると仮定しています。先頭はです。 null値が許可されないようにクラスを設計できれば、コンストラクタなどでこれを検証すれば、コードがきれいになる可能性が高くなります。

ここでは、2つの代替アプローチがあります - 別の答えでChrisによって提出されたアプローチは、各プロパティの "デフォルト"オブジェクトを作成することです。 I 通常コンストラクタには常に「実際の」値を指定することをお勧めします。実際のデータを持たないデフォルトのオブジェクトは、「ダミー」データと一緒に長時間幸せに行くことができ、最後に間違った結果を得るため、NullReferenceExceptionの問題よりも追跡しにくいバグを引き起こす可能性があります。確かにそれはです - 特にコレクションになると、正しいことです。状況によって異なります。

EDIT:Saeedはコメントに拡張方法を提案しました。私は間違いなく他の場所でnull以外のものを維持しようとしているのアイデアを好むが、あなたがそれを必要とする場合、これはそれを行います

(適切なタイプのために調整します。)

public static int? PupilAgeOrNull(this School school) 
{ 
    return school != null && 
      school.ClassRoom != null && 
      school.ClassRoom.Pupil != null 
      ? school.ClassRoom.Pupil.Age : null; 
} 

:私はこのようなものだろうと仮定します。それは私に間違って感じる。この腸の心の中心には、あなたが3〜4つのプロパティをナビゲートしているという事実があります。これは私にLaw of Demeterの違反のように感じます。今私はそのようなことについて独断を覚える人ではありませんが、延長メソッドSchoolに置くことは、このような長い道のりのために私にはあまりにも具体的です。そして、あなたが書くことができます

public static ClassRoom ClassRoomOrNull(this School school) 
{ 
    return school == null ? null : school.ClassRoom; 
} 

public static Pupil PupilOrNull(this ClassRoom classRoom) 
{ 
    return classRoom == null ? null : classRoom.Pupil; 
} 

public static int? AgeOrNull(this Pupil pupil) 
{ 
    return pupil == null ? null : pupil.Age; 
} 

別の選択肢 - - もやや厄介で、IMO三つの異なる拡張メソッドを書くことです

int? age = School.ClassRoomOrNull().PupilOrNull().AgeOrNull(); 
if (age != null) 
{ 
    MyMethod(age); 
} 

このことは、School上の拡張メソッドそれほど具体的ではありません。あなたはまだメソッド呼び出しの長い連鎖を持っていますが、私は可能な限りこの状況を避けるためにまだ再設計しようとしていますが、少なくともSchoolからSchool.ClassRoom.Pupil.Ageまではあまりタイトではありません。

+0

彼は 'if'の代わりにこれをしたいと望んでいます。 –

+0

@Saeed:Um、どこで拡張メソッドを言いましたか? –

+1

if(School.IsNullAge())そのような関数を書くのは簡単ですが、なぜ彼はこれを言いたいのですか?醜いコードを好きではないのですか? –

1

あなたが示したコードを与えると、より簡単な方法はありません。各コンポーネントを確認する必要があります。

if (School != null && School.ClassRoom != null 
    && School.ClassRoom.Pupil != null 
    && School.ClassRoom.Pupil.Age != null) 
{ 
    ... 
} 

ただし、メンバーがnullことはありませんようにコードを書くことができます。そうすれば、nullを確認する必要がなくなります。例

class School 
{ 
    private ClassRoom _classRoom = new ClassRoom(); 

    public ClassRoom ClassRoom 
    { 
    get {return _classRoom;} 
    } 
} 

のためにこれは学校にして開始するための空のクラスの部屋を与えるので、それはnullではなく、プロパティはセッターを持っていないので、クラスのnull外に設定することはできません。あなたはこのコンセプトを進歩させることができます。生徒のリスト(私はこれがリストであると仮定します)はnullインスタンスではなく空リストになります。

1

"Null-Object Pattern"があなたの救助になります。 hereを読んでください。

したがって、NullSchool、NullClassRoom、NullPupil、NullAgeを持つことができます。

次に、有効でない場合は年齢を拒否するMyMethodのチェック(または、AgeクラスのIsValid()のようなメソッド)をMyMethod内に1つだけ持つことができます。

+0

それは救助に来るかもしれない。本当に*賢明な "ヌル"バージョンであるかどうかによって異なります。私の答えで書いたように、ダミーデータを提供することは、診断が困難な問題に簡単につながる可能性があります。 –

2

Hereは、エクスプレッションツリーで素敵で洗練されたソリューションです。 試してみてください!

関連する問題