Update: Ab Visual Studio 2015 erkennt der C # -Compiler (Sprachversion 6) jetzt den ?.
Operator, was das "Deep Null Checking" zum Kinderspiel macht. Siehe diese Antwort für Details.
Abgesehen von der Neugestaltung Ihres Codes, wie in
dieser gelöschten Antwort vorgeschlagen, besteht eine andere (wenn auch schreckliche) Option darin, einen try…catch
Block zu verwenden, um festzustellen, ob NullReferenceException
irgendwann während dieser tiefen Eigenschaftssuche ein Fehler auftritt.
try
{
var x = cake.frosting.berries.loader;
...
}
catch (NullReferenceException ex)
{
// either one of cake, frosting, or berries was null
...
}
Ich persönlich würde dies aus folgenden Gründen nicht tun:
- Es sieht nicht gut aus.
- Es verwendet die Ausnahmebehandlung, die auf Ausnahmesituationen abzielen sollte und nicht auf etwas, das Sie im normalen Betriebsverlauf häufig erwarten.
NullReferenceException
s sollte wahrscheinlich nie explizit gefangen werden. (Siehe diese Frage .)
Ist es also möglich, eine Erweiterungsmethode zu verwenden, oder wäre es eine Sprachfunktion, [...]
Dies müsste mit ziemlicher Sicherheit eine Sprachfunktion sein (die in C # 6 in Form von .?
und ?[]
Operatoren verfügbar ist ), es sei denn, C # hatte bereits eine ausgefeiltere verzögerte Auswertung oder Sie möchten Reflektion verwenden (was wahrscheinlich auch keine ist gute Idee aus Gründen der Leistung und Typensicherheit).
Da es keine Möglichkeit gibt, einfach cake.frosting.berries.loader
an eine Funktion zu übergeben (sie würde ausgewertet und eine Nullreferenzausnahme auslösen), müssten Sie eine allgemeine Suchmethode folgendermaßen implementieren: Sie nimmt Objekte und die Namen von Eigenschaften auf Sieh nach oben:
static object LookupProperty( object startingPoint, params string[] lookupChain )
{
// 1. if 'startingPoint' is null, return null, or throw an exception.
// 2. recursively look up one property/field after the other from 'lookupChain',
// using reflection.
// 3. if one lookup is not possible, return null, or throw an exception.
// 3. return the last property/field's value.
}
...
var x = LookupProperty( cake, "frosting", "berries", "loader" );
(Hinweis: Code bearbeitet.)
Sie sehen schnell mehrere Probleme mit einem solchen Ansatz. Erstens erhalten Sie keine Typensicherheit und kein mögliches Boxen von Eigenschaftswerten eines einfachen Typs. Zweitens können Sie entweder zurückkehren, null
wenn etwas schief geht, und Sie müssen dies in Ihrer aufrufenden Funktion überprüfen, oder Sie lösen eine Ausnahme aus, und Sie kehren zu Ihrem Ausgangspunkt zurück. Drittens könnte es langsam sein. Viertens sieht es hässlicher aus als das, womit Sie begonnen haben.
[...] oder ist es nur eine schlechte Idee?
Ich würde entweder bleiben bei:
if (cake != null && cake.frosting != null && ...) ...
oder gehen Sie mit der obigen Antwort von Mehrdad Afshari.
PS: Als ich diese Antwort schrieb, habe ich offensichtlich keine Ausdrucksbäume für Lambda-Funktionen berücksichtigt. Siehe zB die Antwort von @driis für eine Lösung in dieser Richtung. Es basiert auch auf einer Art Reflexion und ist daher möglicherweise nicht ganz so gut wie eine einfachere Lösung ( if (… != null & … != null) …
), kann jedoch aus syntaktischer Sicht besser beurteilt werden.