2010-05-14 31 views
21

Por lo que yo sé que no es una forma más elegante significativamente para escribir la siguiente ....taquigrafía para comprobar nula anidada C#

string src; 
if((ParentContent!= null) 
    &&(ParentContent.Image("thumbnail") != null) 
    &&(ParentContent.Image("thumbnail").Property("src") != null)) 
    src = ParentContent.Image("thumbnail").Property("src").Value 

¿Cree que debería ser una característica del lenguaje C# para hacer esto más corto?
Y si es así, ¿qué aspecto debería tener?
por ejemplo, algo así como extender el ?? operador

string src = ParentContent??.Image("thumbnail")??.Property("src")??.Value; 

Disculpas por el ejemplo bastante artificial, y mi solución demasiado simplificada.

Editar ... Muchos años después
Esto es ahora una característica del lenguaje planificada llamado el "operador de propagación nulo" ?. https://roslyn.codeplex.com/discussions/540883 (Gracias @ Brian)

+0

¡Definitivamente apela a mi golosa! –

+1

Consulte https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status&referringTitle=Documentation y https://roslyn.codeplex.com/discussions/540883. Esta característica debería estar disponible pronto. – Brian

+0

¡Viene en C# 6! –

Respuesta

18

No hay está incorporado en la sintaxis para hacer esto, pero se puede definir un método de extensión para hacer esto:

R NotNull<T, R>(this T src, Func<T, R> f) 
    where T : class where R : class { 
    return src != null ? f(src) : null; 
} 

Ahora, puede volver a escribir tu ejemplo de la siguiente manera:

src = ParentContent.NotNull(p => p.Image("thumbnail")). 
     NotNull(i => i.Property("src")).NotNull(src => src.Value); 

No es tan agradable como puede ser con un soporte sintáctico, pero diría que es mucho más legible.

Tenga en cuenta que esto agrega el método NotNull a todos los tipos .NET, lo que puede ser un poco incómodo. Podría resolverlo definiendo un envoltorio simple tipo WrapNull<T> where T : class que contenga solo un valor de tipo T y un método para convertir cualquier tipo de referencia en WrapNull y proporcione el NotNull en el tipo WrapNull. A continuación, el código se vería así:

src = WrapNull.Wrap(ParentContent).NotNull(p => p.Image("thumbnail")). 
     NotNull(i => i.Property("src")).NotNull(src => src.Value); 

(por lo que no contamina el IntelliSense de todo tipo con el nuevo método de extensión)

Con un poco más de esfuerzo, se puede también definir una consulta LINQ operadores para hacer esto. Esto es un poco exagerado, pero es posible escribir esto (no incluiré las definiciones aquí porque son un poco más largas, pero es posible en caso de que alguien esté interesado :-)).

src = from p in WrapNull.Wrap(ParentContent) 
     from i in p.Image("thumbnail"). 
     from src in i.Property("src") 
     select src.Value; 
+2

Tengo que decir que tuve que leer eso unas 5 veces para asimilarlo correctamente. A veces, leer código funcional me hace arrepentirme de comenzar con los lenguajes de estilo de procedimiento en lugar de decir LISP. Otros días, ¡agradezco mi cordura! ¡No lo hice! : D – Serapth

+0

@Serapth: creo que una cosa es leer la implementación (y entender cómo funciona) y otra cosa es leer el código de usuario. Explicar cómo usar mi método de extensión 'NotNull' no debería ser tan difícil (tal vez no hice tan buen trabajo aquí :-)). –

+0

Oh no, estoy de acuerdo por completo. En realidad, usar el método de extensión no es obvio y es completamente legible, mucho más que la solución original recomendada. Es el método de extensión en sí que me resulta tremendamente difícil de leer. Dicho esto, la programación funcional no es naturalmente intuitiva para mí y, a decir verdad, siempre he encontrado que el código de plantilla agrega una capa de confusión al escenario también. Creo que es solo como mi cerebro está conectado. Entiendo la sintaxis, lo que está sucediendo y cómo funciona, solo tengo que leerlo una y otra vez para seguir cómo funciona. – Serapth

16

Se ha sugerido y al parecer rechazado por el equipo:

A bit more C# syntactic sugar for nulls

la sintaxis propuesta habría mirado l ike a.?b.?c() - muy útil y sin ambigüedades.

Realmente me gustaría verlo también, pero no parece que vaya a suceder. ¡Tal vez si suficientes personas lo votan!

+3

+1 votaré –

15

Lo consideramos para C# 4 pero no teníamos el presupuesto. Es una buena característica que muchas personas solicitan, así que tal vez la incorporemos a una futura versión de lenguaje hipotético. Sin promesas.

+9

Algún día, Eric habrá tenido un día largo y estará demasiado cansado. Y ese día, él dirá: "estamos considerando esto para la próxima versión de C#". – Brian

+1

¡Sigue considerando! :-) – Myster

+0

Por favor, sigan teniendo en cuenta ... 3 años después :) – Jack

0

todavía deja un poco que desear, pero me gustaría escribir así:

var src = ParentContent == null ? null 
    : ParentContent.Image("thumbnail") == null ? null 
    : ParentContent.Image("thumbnail").Property("src") == null ? null 
    : ParentContent.Image("thumbnail").Property("src").Value; 
1

me corrija si estoy equivocado, pero esto podría resolverse usando C# de 6,0 null-conditional operator:

string src = ParentContent?.Image("thumbnail")?.Property("src")?.Value; 

Si src ya está en uso antes de que esta asignación de valor, se podría utilizar de la siguiente manera:

string src = ....; 

// ... 

src = ParentContent?.Image("thumbnail")?.Property("src")?.Value ?? src; 

// ...