2009-02-26 20 views
8

Lo he visto en el código heredado y en algunos proyectos de fuente abierta .NET. No puedo imaginar una razón para hacer esto. Simplemente usar "nulo" me parece mucho más fácil.¿Por qué las personas usan valores de magia en lugar de nulo en su código?

Ejemplo:

public class Category 
{ 
    int parentID; 

    bool HasParent 
    { 
     get 
     { 
      return parentID != -1; 
     } 
    } 
} 

frente

public class Category 
{ 
    int parentID; 

    bool HasParent 
    { 
     get 
     { 
      return parentID != null; 
     } 
    } 
} 
+0

Haría mucho mejor si mostrara un ejemplo al menos. – GEOCHET

+0

-1: sin código. -1: no hay problema ¿Cuál es el problema? ¿Qué no funciona? –

+0

Ha invertido el cheque (debería ser parentID! = Null), pero creo que la pregunta es válida. +1 – erikkallen

Respuesta

0

que realmente han estudiado la aplicación para ver? Siempre que el número mágico se mantenga en un solo lugar con un nombre descriptivo, puede ser bastante útil.

+0

Sí, se mantienen en un solo lugar con un valor descriptivo, como Null.NullInteger y Null.NullDate, pero no pude averiguar por qué es útil – Paco

+0

Entonces, no es un "valor mágico" en absoluto, los valores mágicos son literales en el código fuente que no tienen contexto y, por lo tanto, tienen un significado ambiguo. –

+0

Considero que es un valor mágico porque debe saber que no es solo un número entero o una fecha, sino que debe compararlo con el Null.NullObject para saber lo que significa. No puede saber que tiene que compararlo con el nullobject antes de usar el valor. – Paco

3

Tener un objeto nulo puede provocar que se generen excepciones, mientras que los códigos de error (como un caso de falla "-1") no generarán una excepción.

Esto puede ser crítico en idiomas o aplicaciones que no manejan bien las excepciones.

2

Al trabajar en grandes datawarehouses, a veces uso el valor 0 en cambio si nulo, para insertar un valor no nulo en mi cubo. siempre tengo un 0 id correspondiente al valor "Desconocido" en todas las dimensiones, así que tengo un cubo sin valores nulos.

el principal interés en que es tener más simple y consultas más eficaces

4

Estos son a menudo los hábitos desarrollados durante la programación en C. Más de un programador de C se horified en los residuos de enteros con valores nulos, que por lo menos requiere un bit adicional completo, y posiblemente incluso un puntero. Esto es especialmente malo cuando sabes que el valor va a ser positivo y tienes todo el espacio de valores negativos para usar para las banderas. -1 puede significar que no se establece, -2 puede significar que parentId ni siquiera tiene sentido en el contexto de este nodo, -3 puede significar que el nodo tenía un padre que no podía manejar el trabajo y se fue en un atracón de bebida y nunca se volvió a ver, etc ...

En el mundo C#, la nitidez de las notas que aceptan nulos (y su fácil integración con RDMS) junto con las computadoras con 2GB + de RAM significa que los viejos hábitos C están muriendo lentamente, pero viejos hábitos morir duro.

1

Los tipos de valores anulables no están disponibles en todos los idiomas/entornos; Se agregaron a .Net 2.0. Si su código heredado está basado en .Net y se comenzó a usar el marco 1.1, entonces su respuesta es que null no era una opción en ese momento.

11

Porque para tener un valor "nulo", el tipo debe ser anulable. Esto funciona bien para los tipos de referencia (cualquier clase que se define y la biblioteca estándar), y si te fijas verás que las personas hacen utilización nula siempre que tengan un objeto de referencia sin valor

Employee employee = Employees.Find("John Smith"); 
if(employee == null) throw new Exception("Employee not found"); 

La cuestión viene cuando usa valor tipos como int, char o float. A diferencia de los tipos de referencia, que apuntan a un bloque de datos en otro lugar de la memoria, estos valores se almacenan y manipulan en línea (no hay puntero/referencia).

Debido a esto, de forma predeterminada, los tipos de valor no tienen un valor nulo. En el código que proporcionó, es imposible para que parentID sea nulo (estoy realmente sorprendido de que esto haya pasado con su compilador: Visual Studio 2008 y probablemente 2005 dibujará un subrayado verde y le dirá que la declaración es siempre falsa) .

Para que un int tener un valor nulo, es necesario declarar como anulable

int? parentID; 

Ahora parentID puede contener un valor nulo, porque ahora es un puntero (bueno " referencia ") a un entero de 32 bits, en lugar de solo un entero de 32 bits.

Espero que comprenda por qué los "valores mágicos" se utilizan a menudo para representar null con los tipos básicos (tipos de valores). Es simplemente un montón de problemas, y a menudo un gran golpe de rendimiento (buscar lo que es el boxeo/unboxing), para almacenar estos tipos de valores como una referencia al valor para permitir que sean nulos.

Editar: Para mayor referencia sobre el boxeo/unboxing (lo que es necesario tener un int == null), ver el artículo en MSDN:

Boxing y unboxing (C# Guía de programación)

Rendimiento

En relación con las asignaciones simples, el boxeo y el desempaquetado son procesos computacionalmente costosos. Cuando se encuadra un tipo de valor, se debe asignar y construir un nuevo objeto. En menor grado, el elenco requerido para el desempaquetado también es costoso computacionalmente. Para obtener más información, vea Rendimiento.

+0

No me puedo imaginar un caso en el que esta pequeña ganancia de rendimiento sea crítica. – Paco

+2

La sobrecarga * no es pequeña *: está hablando de agregar operaciones de boxeo/desempaquetado a las operaciones y tipos de datos * fundimentales. Un punto de referencia que realiza una operación de suma condicional entera se ejecuta 9 veces más lento cuando los valores son anulables debido a la sobrecarga del boxeo. Pruébalo por ti mismo. – David

+0

Sé cuánto tiempo lleva, pero no creo en la optimización de los algoritmos O (N). – Paco

Cuestiones relacionadas