2009-10-23 23 views
5

yo estaba trabajando en algún código y sorprendí a mí mismo haciendo este errorC# Operadores y legibilidad

if (stringName == "firstName" || "lastName") 
    // Do code 

obviamente esto está mal y debe ser

if (stringName == "firstName" || stringName == "lastName") 
    // Do code 

pero simplemente me hizo pensar en lo que respecta a la legibilidad sería la primera más fácil? Tal vez tenga alguna lógica que pueda decir, a menos que se especifique un nuevo stringName, ¿usar el primero?

Realmente no es una pregunta, solo tengo curiosidad si hay algo que no entiendo completamente sobre la lógica detrás de la compilación de una declaración como esta.

+0

Puede utilizar Sobrecarga de operador. Por ejemplo, puede crear una clase que contenga una lista de cadenas (lo llamaremos foo), use sobrecarga del operador: make string || string return foo (Obviamente, con la cadena en el contenedor) y make foo || string debería agregar la cadena y devolver foo. (Entonces puede usar string || string || string) luego puede sobrecargar string == foo para que finalmente pueda compararlos. Entonces, ¿respuesta corta? Operador sobrecargando rocas! –

Respuesta

10

El problema es que si funciona en booleanos.

stringName == "firstName" devuelve un valor booleano.
"lastName" es una cadena literal.

|| es un booleano u operador cortocircuitado que toma booleanos en ambos lados.

En otras palabras, desea cambiar la definición de || que generalmente es una mala idea.

En teoría, podría hacer que el analizador de puntos inferiera lo que quiere decir ... pero eso se vuelve ambiguo muy rápidamente.

if (stringName == firstName || lastName) 

Se ve bien, ¿no? Pero, ¿qué es exactamente lastName?

¿Qué sucede si hago esto?

const bool lastName = false; 

Además, && es lo contrario de ||, pero stringName == firstName && lastName no es lo contrario de la lógica anterior, y de hecho no tendría sentido.

+0

Esa última línea es exactamente lo que me faltaba. –

1

La razón por la que no permitieron tal sintaxis fue muy probablemente debido a la legibilidad. Si está mirando el código por primera vez y no está exactamente en su mejor estado de ánimo, es posible que no vea inmediatamente que está comparando stringName con "firstName" y "lastName". Simplemente hace que tus intenciones sean mucho más definidas.

Por otra parte, los paréntesis podrían resolver eso.

1

Eso solo funcionaría si devolviera operator||(string,string) .. un tipo de colección de cadenas y tenía una sobrecarga Equals que tomó una cadena y esa colección de cadenas y verificó que la cadena está en la colección. Parece mucho trabajo realizado detrás de las escenas para una construcción muy raramente utilizada.

Sobre todo porque ya se puede hacer algo como:

if(new string[]{"firstName","lastName"}.Contains(stringName)) 
    // code 
+1

De hecho, creo que es menos legible que antes. –

+0

Esa es una cuestión de gusto. Si dijiste que es un desperdicio, entonces estaría de acuerdo, crea una matriz solo para comparar algunos valores. – Blindy

+0

La misma técnica es definitivamente más legible en otros idiomas: 'if stringName in (" firstName "," lastName ") ...' (Python) –

6

Tener la conjetura compilador en la intención del programador cuando el código es claramente erróneo con el fin de solucionarlo es una muy, muy mala idea.

+0

De acuerdo en que es incorrecto y que el compilador adivine es incorrecto pero ¿de qué otra forma podría ser esto? ¿destinado a? –

+0

Quizás intentaste usar otra variable 'otherStringName' - ¿cómo va a saber el compilador? – tvanfosson

+0

Veo lo que dices, parece redundante. ¡Gracias! –

11

Creo que su propuesta enturbiaría las reglas de análisis de expresiones - ahora, el '==' se convierte en un operador cuadrencial (?), En lugar de uno binario. Me he encontrado falta operador 'IN' de SQL, sin embargo, and've usado algo como esto:

if (stringName.In("foo", "bar", "baz")) 
{ 

} 

// in an extension method class 
public static bool In<T>(this T value, params T[] values) 
{ 
    return values.Contains(value); 
} 
+0

o hazlo genérico: 'En (este valor T, params T [] valores)' – Lucas

+0

@Lucas: excelente sugerencia! Incorporado. –

1

encuentro la contains() la función resuelve este problema es decir:

string[] ValidNames = new string[] { "firstName", "lastName"}; 

if(ValidNames.Contains(stringName)) 
{ 
    //Do Code 
} 
1

I wouldn No importa una sintaxis similar a SQL de:

if(stringName in ("firsName", "lastName")) 
{ 
} 
+1

Parece Python. –

+0

Su respuesta aborda el objetivo de la pregunta, en lugar de la falla en la sintaxis sugerida del OP, por lo que +1. – Greg

+0

ver la respuesta de Petrotta arriba: http://stackoverflow.com/questions/1615800/c-operators-and-readability/1615835#1615835 – Lucas

2

Incluso con paréntesis, no tiene sentido. stringName == ("firstName" || "lastName") parece que quiere probar la verdad de las dos cadenas, y esas cadenas siempre serán verdaderas, y luego comparar ese resultado booleano con la cadena stringName.

Si agrega paréntesis como éste (stringName == "firstName") || "lastName", la condición es también siempre va a ser cierto, ya que "lastName" siempre es cierto independientemente de si es o no es igual a stringName"firstName".

me gusta la forma en Rubí de hacerlo:

["firstName", "lastName"].include? stringName 

Siempre se puede utilizar Contains como otros han sugerido o escribir un método de extensión de cadena a donde se podía hacer:

stringName.EqualsOneOf(new[] {"firstName", "lastName"}) 
0

Esta es la razón, como un hábito, que siempre hago:

if ((stringName == "firstName") || (stringName == "lastName")) 
    // Do code 

Después de un tiempo se convierte en una segunda naturaleza.

0

Cuando la FCL contiene la riqueza para crear la gran variedad de respuestas que se ven en este hilo, no necesita tener una sintaxis C# más flexible porque la legibilidad se convierte rápidamente en una característica de cómo se crea la respuesta entre toda la riqueza . Se reduce a elecciones entre métodos y llamadas a objetos la mayor parte del tiempo.

Aquí hay un ejemplo (solo otro de muchos) de poder ubicar una o varias cadenas simultáneamente en una matriz de cadenas, o para aplicar cualquier otro criterio que considere adecuado para ese conjunto de cadenas. La sangría, el espaciado y los comentarios de código juegan un papel importante para entender este ejemplo de código, como para cualquier código.

 bool found = Array.Exists(
      // array of strings to search 
      new[] { "c#", ".net", "programming", "design patterns", "work", "play", "bits", "bytes", "break" }, 
      // criteria - can even satisfy multiple conditions simultaneously if desired 
      str => (str == ".NET" || str == "work") //look for ".NET" or "work" 
      );