Actualización: a partir de Visual Studio 2015, el compilador de C # (versión de lenguaje 6) ahora reconoce al ?.
operador, lo que hace que la "comprobación nula profunda" sea muy sencilla. Ver esta respuesta para más detalles.
Además de rediseñar su código, como
sugiere esta respuesta eliminada , otra opción (aunque terrible) sería usar un try…catch
bloque para ver si NullReferenceException
ocurre en algún momento durante esa búsqueda profunda de propiedades.
try
{
var x = cake.frosting.berries.loader;
...
}
catch (NullReferenceException ex)
{
// either one of cake, frosting, or berries was null
...
}
Yo personalmente no haría esto por las siguientes razones:
- No se ve bien.
- Utiliza el manejo de excepciones, que debe enfocarse en situaciones excepcionales y no en algo que usted espera que suceda a menudo durante el curso normal de la operación.
NullReferenceException
s probablemente nunca debería ser atrapado explícitamente. (Ver esta pregunta )
Entonces, ¿es posible usar algún método de extensión o sería una función de idioma, [...]
Es casi seguro que tendría que ser una función de lenguaje (que está disponible en C # 6 en forma de .?
y?[]
operadores), a menos que C # ya tenía más sofisticado evaluación perezosa, o menos que desee utilizar la reflexión (que probablemente no es también una buena idea por razones de rendimiento y seguridad de tipo).
Como no hay forma de pasar simplemente cake.frosting.berries.loader
a una función (se evaluaría y arrojaría una excepción de referencia nula), tendría que implementar un método de búsqueda general de la siguiente manera: toma objetos y los nombres de propiedades para buscar:
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: código editado).
Rápidamente ve varios problemas con este enfoque. Primero, no obtienes ningún tipo de seguridad y posible boxeo de valores de propiedad de un tipo simple. En segundo lugar, puede regresar null
si algo sale mal, y tendrá que verificar esto en su función de llamada, o lanzará una excepción y volverá a donde comenzó. Tercero, puede ser lento. Cuarto, parece más feo de lo que comenzaste.
[...], ¿o es solo una mala idea?
O me quedaría con:
if (cake != null && cake.frosting != null && ...) ...
o vaya con la respuesta anterior de Mehrdad Afshari.
PD: Cuando escribí esta respuesta, obviamente no consideraba los árboles de expresión para las funciones lambda; vea, por ejemplo, la respuesta de @driis para una solución en esta dirección. También se basa en un tipo de reflexión y, por lo tanto, podría no funcionar tan bien como una solución más simple ( if (… != null & … != null) …
), pero puede considerarse mejor desde el punto de vista de la sintaxis.