Aggiornamento: a partire da Visual Studio 2015, il compilatore C # (lingua versione 6) ora riconosce l' ?.operatore, il che rende un "controllo null profondo" un gioco da ragazzi. Vedi questa risposta per i dettagli.
Oltre a riprogettare il tuo codice, come
suggerito da questa risposta cancellata , un'altra (anche se terribile) opzione sarebbe quella di utilizzare un try…catchblocco per vedere se si NullReferenceExceptionverifica a volte durante quella ricerca approfondita della proprietà.
try
{
var x = cake.frosting.berries.loader;
...
}
catch (NullReferenceException ex)
{
// either one of cake, frosting, or berries was null
...
}
Personalmente non lo farei per i seguenti motivi:
- Non sembra carino.
- Utilizza la gestione delle eccezioni, che dovrebbe riguardare situazioni eccezionali e non qualcosa che ti aspetti che accada spesso durante il normale corso dell'operazione.
NullReferenceExceptionprobabilmente non dovrebbero mai essere catturati in modo esplicito. (Vedi questa domanda .)
Quindi è possibile usare un metodo di estensione o sarebbe una funzione linguistica, [...]
Questo dovrebbe quasi certamente essere una caratteristica del linguaggio (che è disponibile in C # 6 sotto forma di .?e ?[]operatori), a meno che C # non abbia già avuto una valutazione pigra più sofisticata, o a meno che tu non voglia usare la riflessione (che probabilmente non è nemmeno una buona idea per motivi di prestazioni e sicurezza del tipo).
Poiché non è possibile passare semplicemente cake.frosting.berries.loadera una funzione (verrebbe valutata e generata un'eccezione di riferimento null), è necessario implementare un metodo di ricerca generale nel modo seguente: accetta un oggetto e i nomi delle proprietà per consultare:
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" );
(Nota: codice modificato.)
Si vedono rapidamente diversi problemi con un simile approccio. Innanzitutto, non si ottiene alcuna sicurezza di tipo e possibili inscatolamento di valori di proprietà di un tipo semplice. In secondo luogo, puoi tornare nullse qualcosa va storto e dovrai verificarlo nella tua funzione di chiamata, oppure lanciare un'eccezione e tornare al punto di partenza. Terzo, potrebbe essere lento. In quarto luogo, sembra più brutto di quello con cui hai iniziato.
[...] o è solo una cattiva idea?
O starei con:
if (cake != null && cake.frosting != null && ...) ...
o vai con la risposta sopra di Mehrdad Afshari.
PS: Quando ho scritto questa risposta, ovviamente non ho considerato gli alberi delle espressioni per le funzioni lambda; vedi ad esempio la risposta di @driis per una soluzione in questa direzione. È anche basato su un tipo di riflessione e quindi potrebbe non funzionare altrettanto bene come una soluzione più semplice ( if (… != null & … != null) …), ma può essere giudicato più bello dal punto di vista della sintassi.