2009-02-17 5 views
5

En idiomas funcionales a menudo existe una mónada Maybe que le permite encadenar múltiples llamadas en un objeto y devolver toda la expresión None/null si cualquier parte de la cadena se evalúa a nada, en lugar de la típica NullReferenceException que obtendría en C# encadenando llamadas donde un objeto podría ser nulo.¿Sería bueno un operador de referencia condicional en C#?

Esto se puede implementar de manera trivial escribiendo un Maybe<T> con algunos métodos de extensión para permitir un comportamiento similar en C# usando comprensiones de consulta, que pueden ser útiles al procesar XML con elementos/atributos opcionales.

var val = from foo in doc.Elements("foo").FirstOrDefault().ToMaybe() 
      from bar in foo.Attribute("bar").ToMaybe() 
      select bar.Value; 

Pero esta sintaxis es un poco torpe y poco intuitivo que la gente está acostumbrada a tratar con secuencias en LINQ en lugar de elementos individuales, y que te deja con un Maybe<T> en lugar de un T al final. ¿Sería un operador de referencia condicional (por ejemplo, ..) suficientemente útil para convertirlo en el idioma? p.ej.

var val = doc.Elements("foo").FirstOrDefault()..Attribute("bar")..Value; 

El condicional de referencia se expandiría a algo como:

object val; 
var foo = doc.Elements("foo").FirstOrDefault(); 
if (foo != null) 
{ 
    var bar = foo.Attribute("bar"); 
    if (bar != null) 
    { 
     val = bar.Value; 
    } 
    else 
    { 
     val = null; 
    } 
} 

puedo ver que esto podría conducir a terribles abusos como el uso de .. todas partes para evitar una NullReferenceException, pero por otra parte cuando se usa adecuadamente, puede ser muy útil en bastantes situaciones. ¿Pensamientos?

+0

Me gusta la idea, mucho. Sugeriría usar algo diferente '' '. Quizás '??.'. En cualquier caso, algo que no sea un solo error común fuera de '.'. –

Respuesta

1

Encadenar llamadas múltiples en un objeto me hace temer infracciones del Law of Demeter. Por lo tanto, soy escéptico de que esta característica sea una buena idea, al menos en términos de resolver el problema específico que está utilizando como ejemplo.

+0

Elegí específicamente el ejemplo XML para mostrar una situación en la que es virtualmente imposible * no * infringir esta ley mientras hago algo realmente útil, ya que XML es una estructura de árbol bien documentada donde no creo que esta ley realmente se aplique. –

+0

El problema con la Ley de Demeter es que alguien lo llamó "Ley de Demeter" en lugar de "Guía de Demeter", que es lo que es. Las pautas están ahí para guiarnos, pero no deberían ser un obstáculo para una buena idea. –

+0

Yo respondería que esto es para lo que es xpath, pero puedo ver donde una cadena pura sería considerada más fea por algunos. Dicho eso, la mayoría de las veces esto NO es algo que quieras hacer. – Brian

0

Es una idea interesante que se puede lograr con un método de extensión. Algo como esto, por ejemplo (nota, sólo por ejemplo - Estoy seguro de que puede ser refinado):

public static IEnumerable<T> Maybe<T>(this IEnumerable<T> lhs, Func<IEnumerable<T>, T> rhs) 
{ 
    if (lhs != null) 
    { 
    return rhs(lhs); 
    } 

    return lhs; 
} 
0

Sospecho una combinación de contener nulos y los métodos de extensión permitiría que una parte significativa de este a B logra.

Esto limitaría T a los tipos de valor, por supuesto.

(TBH yo preferiría ver el apoyo tupla en el langauge y eliminar a cabo parámetros, como F # hace.)

código se puede simplificar, poner val como nulo y se eliminan las ramas demás.

-2

Puedo ver la utilidad potencial, pero aparte de un ligero impacto en el rendimiento si los elementos a menudo son nulos, ¿por qué no rodear el bloque de código con un bloque try..catch para una NullReferenceException?

+0

El problema con usar un try/catch es que te saca de la consulta. Con una operación que hace frente a nulo, la consulta puede completar y dar un resultado válido, que podría ser muy útil si tiene varias expresiones en su consulta. –

+0

Excepciones para el control de flujo prácticamente nunca es una buena idea ... No entraré en por qué aquí; hay mucha información en este sitio y en Internet en general sobre esto. –

+0

Ahh, tenía la impresión de que no se obtendría ningún resultado válido si una de las partes de la consulta devolviera un valor nulo; simplemente no generaría un error. En cuanto al uso de Excepciones para control de flujo, estoy de acuerdo, y es por eso que mencioné que los elementos no suelen ser nulos. –

Cuestiones relacionadas