2009-04-20 7 views
1

Ich habe eine Frage zu Programmierstil und C# -Sprachendesign im Allgemeinen. Ich würde gerne wissen, ob es einen besseren Weg gibt, das zu tun, was ich mache.C# Nested null checks in if Anweisungen

Wenn Sie ein komplexes Datenobjekt haben, mit Eigenschaften, die null sein können, aber Sie wollen auf Daten überprüfen oder zu betreiben, wenn es da ist, kann man keine Zeile schreiben wie so

if(Myobject.MyNestedObject != null || Myobject.MyNestedObject.Property != null) 
{ 
    //code 
} 

Da der Compiler Rufen Sie beide Codezeilen tatsächlich auf, um die if-Anweisung auszuwerten.

Stattdessen muss man (glaube ich) schreiben:

if(Myobject.MyNestedObject != null) 
{ 
    if(Myobject.MyNestedObject.Property != null) 
    { 
     //code 
    } 
} 

Gibt es eine bessere Art als das? Ich versuche, darüber nachzudenken, wie man null coalesce (??) verwendet, aber es würde immer noch werfen, wenn Sie versuchen, etwas von MyNestedObject in derselben Anweisung zu verwenden.

Weitere Informationen:

L_01b4: ldarg.1 
    L_01b5: callvirt instance class [Myassembly]MyClass.MyObject [MyAssembly]MyClass::get_MyObject() 
    L_01ba: brtrue.s L_01cc 
    L_01bc: ldarg.1 
    L_01bd: callvirt instance class [MyAssembly]MyClass.MyObject [MyAssembly]MyClass::get_MyObject() 
    L_01c2: callvirt instance class [MyAssembly]MyClass.MyNestedObject [MyAssembly]MyClass.MyNestedObject::get_MyNestedObject() 
    L_01c7: ldnull 
    L_01c8: ceq 
    L_01ca: br.s L_01cd 
    L_01cc: ldc.i4.0 
    L_01cd: stloc.2 
    L_01ce: ldloc.2 
    L_01cf: brtrue L_0285 
    L_01d4: nop 

Von meinem Verständnis es sagt, dass bei L_01ba, wenn der Anruf true zurückgibt, nicht null oder nicht-0 (dh, wenn das Objekt null ist, wird die Verzweigung nicht genommen und dann Kontrollfluss läuft linear weiter). Dies wird dann natürlich L_01c2 ausführen, was eine Null-Referenz-Ausnahme auslöst, da Myclass.MyObject Null ist.

Habe ich etwas verpasst. Dies ist der .NET 3.5 C# -Compiler.

Antwort

19

Kombination @ Chris und @aJ Antwort mit & werden:.

Ich glaube, Sie wollen den & & Operator, nicht ||

if (Myobject.MyNestedObject != null && 
    Myobject.MyNestedObject.Property != null) 
{ 
    //code 
} 

Und C# &Der Operatorverwendet die Kurzschlussauswertung. Wenn also der erste Ausdruck false zurückgibt, wird der zweite Ausdruck nicht ausgewertet.

...

+0

Eine gute Nachtruhe macht was blutig offensichtlich sein sollte. Indem man die zwei Zeilen schreibt, führt es effektiv aus, was die Operation und die Operation macht. – Spence

2

C# verwendet faul Kontrolle, so dass Ihre erste Code sollte in Ordnung sein

Update - Hier ist sie (mit || zu & & natürlich geändert!): http://msdn.microsoft.com/en-gb/library/6373h346.aspx " Der Betrieb

x || y

entspricht dem Betrieb

x | y

mit der Ausnahme, dass, wenn x wahr ist, y nicht ausgewertet wird (weil das Ergebnis der ODER-Operation unabhängig vom Wert von y wahr ist). Dies wird als "Kurzschluss" -Auswertung bezeichnet. "

-Update wieder - sollte &

+0

Ich glaube, der Begriff ist "kurze Curciting" –

+3

Ausgenommen (wie von @ aJ Antwort) er ist falsch mit || anstatt && in seinem ersten Codeausschnitt. –

+0

Ich leugne nicht, was Sie als Referenz überhaupt gesagt haben, aber ich habe || benutzt und es hat eine Null-Referenz-Ausnahme auf der Linie geworfen ?? Vielleicht hat C# festgestellt, dass es beides überprüfen muss? – Spence

4
if(Myobject.MyNestedObject != null && 
      Myobject.MyNestedObject.Property != null) 
{ 
//code 
} 
+0

Wird nicht kompiliert - "Kann den Typ 'xxxx' nicht in 'bool' konvertieren" – Chris

+0

Selbst wenn dies in C# kompiliert wurde, ist es nicht so lesbar, auch wenn es knapper ist. –

+1

Ich werde bearbeiten, um nach Null zu überprüfen. Meine Hauptaufgabe war es, && zu betonen. –

1

Ich werde den obligatorischen Ratschlag hinzufügen, dass das Durchforsten von Schichten öffentlicher Eigenschaften normalerweise bedeutet, dass Sie zu viel internen Zustand aufdecken, und dass die Klassen, die Sie durchlaufen, diese Arbeit für Sie erledigen sollten. Ich würde auch erwarten, dass ein Objekt sicherstellt, dass seine Eigenschaften nicht Null an erster Stelle zurückgeben.

Es gibt natürlich Randfälle, aber das sind gute Faustregeln.

+0

Ihr perfekt korrekt, aber ich muss XML aus einer alten Quelle konsumieren. Daher sind die Daten, die ich bekomme, immer unvollständig und dieser Code befindet sich im Parser zwischen Rohdaten und einem verwendbaren Objekt. Daher muss ich überall Nullen überprüfen, weshalb ich wissen wollte, ob es ein besseres Muster gibt. – Spence