Voy a ser impopular y decir Sí, es una mala práctica. SI la funcionalidad de su código depende de él para implementar la lógica condicional.
es decir
if(quickLogicA && slowLogicB) {doSomething();}
es bueno pero
if(logicA && doSomething()) {andAlsoDoSomethingElse();}
es malo, y seguramente nadie estaría de acuerdo?
if(doSomething() || somethingElseIfItFailed() && anotherThingIfEitherWorked() & andAlwaysThisThing())
{/* do nothing */}
Razonamiento:
Sus errores de código si ambos lados son evaluados en lugar de simplemente no realizar la lógica. Se ha argumentado que esto no es un problema, el operador 'y' se define en c #, por lo que el significado es claro. Sin embargo, sostengo que esto no es cierto.
Motivo 1. Histórico
Esencialmente, usted está confiando (lo que originalmente se pensó como) una optimización del compilador para proporcionar funcionalidad en su código.
Aunque en c # la especificación del lenguaje garantiza que el operador booleano 'y' haga un cortocircuito. Esto no es cierto para todos los idiomas y compiladores.
wikipeda enumera varios idiomas y su opinión sobre el cortocircuito http://en.wikipedia.org/wiki/Short-circuit_evaluation, ya que puede, hay muchos enfoques. Y un par de problemas adicionales que no voy a abordar aquí.
En particular, FORTRAN, Pascal y Delphi tienen indicadores de compilación que alternan este comportamiento.
Por lo tanto: puede encontrar que su código funciona cuando se compila para su lanzamiento, pero no para la depuración o con un compilador alternativo, etc.
Motivo 2. Diferencias lingüísticas
Como puede ver en wikipedia, no todos los idiomas adoptan el mismo enfoque para cortocircuitos, incluso cuando especifican cómo deben manejarlo los operadores booleanos.
En particular, el operador 'y' de VB.Net no produce cortocircuitos y TSQL tiene algunas peculiaridades.
Dado que es probable que una 'solución' moderna incluya varios idiomas, como javascript, regex, xpath, etc., debe tener esto en cuenta al aclarar la funcionalidad de su código.
Razón 3. Diferencias dentro de un idioma.
Por ejemplo, el if en línea de VB se comporta de manera diferente a su if. Una vez más, en las aplicaciones modernas, su código puede moverse, por ejemplo, el código detrás y un formulario web en línea, debe tener en cuenta las diferencias de significado.
Motivo 4. Su ejemplo específico de comprobación nula del parámetro de una función
Este es un muy buen ejemplo. En eso es algo que todos hacen, pero en realidad es una mala práctica cuando lo piensas.
Es muy común ver este tipo de verificación, ya que reduce sus líneas de código considerablemente. Dudo que alguien lo mencione en una revisión de código. (¡y obviamente de los comentarios y la calificación puedes ver que es popular!)
Sin embargo, falla en las mejores prácticas por más de una razón.
Está muy claro por numerosas fuentes, que la mejor práctica es verificar la validez de sus parámetros antes de usarlos y lanzar una excepción si no son válidos. Su fragmento de código no muestra el código circundante, pero probablemente debería estar haciendo algo como:
if (smartphone == null)
{
//throw an exception
}
// perform functionality
Está llamando a una función desde dentro de la declaración condicional. Aunque el nombre de su función implica que simplemente calcula un valor, puede ocultar los efectos secundarios. p.ej
Smartphone.GetSignal() { this.signal++; return this.signal; }
else if (smartphone.GetSignal() < 1)
{
// Do stuff
}
else if (smartphone.GetSignal() < 2)
{
// Do stuff
}
Las mejores prácticas sugerirían:
var s = smartphone.GetSignal();
if(s < 50)
{
//do something
}
Si aplica estas mejores prácticas a su código, puede ver que su oportunidad de lograr un código más corto mediante el uso del condicional oculto desaparece. La mejor práctica es hacer algo , manejar el caso donde el teléfono inteligente es nulo.
Creo que encontrará que este también es el caso para otros usos comunes. Hay que recordar que también tenemos:
condicionales en línea
var s = smartphone!=null ? smartphone.GetSignal() : 0;
y nula coalescencia
var s = smartphoneConnectionStatus ?? "No Connection";
que proporcionan una funcionalidad similar de longitud de código corto con más claridad
Numerosos enlaces para apoyar todos mis puntos:
https://stackoverflow.com/questions/1158614/what-is-the-best-practice-in-case-one-argument-is-null
Validación de parámetros de constructor en C # - Mejores prácticas
¿Se debe verificar si es nulo si no espera que sea nulo?
https://msdn.microsoft.com/en-us/library/seyhszts%28v=vs.110%29.aspx
https://stackoverflow.com/questions/1445867/why-would-a-language-not-use-short-circuit-evaluation
http://orcharddojo.net/orchard-resources/Library/DevelopmentGuidelines/BestPractices/CSharp
Ejemplos de indicadores del compilador que afectan el cortocircuito:
Fortran: "sce | nosce De manera predeterminada, el compilador realiza una evaluación de cortocircuito en expresiones lógicas seleccionadas utilizando las reglas de XL Fortran. Especificar sce permite que el compilador use reglas de Fortran no XL. El compilador realizará una evaluación de cortocircuito si las reglas actuales lo permiten . El valor predeterminado es nosce ".
Pascal: "B - Una directiva de bandera que controla la evaluación de cortocircuito. Consulte el Orden de evaluación de operandos de operadores diádicos para obtener más información sobre la evaluación de cortocircuito. Consulte también la opción del compilador -sc para el compilador de línea de comandos para obtener más información ( documentado en el Manual del usuario) ".
Delphi: "Delphi admite la evaluación de cortocircuito de forma predeterminada. Se puede desactivar con la directiva del compilador {$ BOOLEVAL OFF}".