2010-01-28 24 views

Respuesta

10

Esto es según la especificación para los operadores binarios levantados. De §7.2.7:

Para los operadores binarios

+ - */% & |^<< >>

una forma elevada de un operador existe si los tipos de los operandos y resultados son todos los tipos de valor no anulable. La forma elevada se construye agregando un modificador único ? a cada operando y tipo de resultado. El operador elevado produce un valor nulo si uno o ambos operandos son nulos (una excepción son los operadores & y | del tipo bool ?, como se describe en §7.10.3). De lo contrario, el operador levantado desenvuelve los operandos, aplica el operador subyacente y envuelve el resultado.

El razonamiento es el siguiente: usted es pensar en null para un tipo anulable en el sentido de "No sé cuál es el valor." ¿Cuál es el resultado de "No sé" más uno? "No lo sé." Por lo tanto, el resultado debería ser null.

+0

Su lógica está bien redactada, pero realmente debería arrojar una excepción. Piense en + como una manera sintácticamente más fresca de ejecutar el número. Más (2). Definitivamente debería lanzar una excepción si el número es nulo o puede causar un comportamiento inesperado. –

+0

Peor aún, si tiene un número y AGREGUE nulo, será nulo. –

0

Desafortunadamente no es así. El X en x = X + 1 es nulo como en la primera línea, por lo que agrega 1 a nulo, lo que equivale a nulo.

Como se trata de un int anulable, puede utilizar x.HasValue para comprobar si tiene un valor, y luego x.Value para obtener el valor real int cabo

2

¿Por qué se puede esperar del compilador para proyectarlo como int cuando lo has declarado como Nullable? El compilador está haciendo lo que le has indicado y null +1 = null.

Deberás realizar un cobro explícito o marcar x.HasValue antes de intentar agregar un int.

5

Nullables nunca son realmente referencias nulas. Siempre son referencias de objetos. Sus clases internas anulan los operadores == y =. Si se comparan con nulo, devolverán el valor de la propiedad HasValue.

+1

La primera oración es correcta. Las dos oraciones del medio son incorrectas. Nullables son referencias de objetos * nunca *. La estructura Nullable no * anula * el operador de igualdad. No existe la posibilidad de anular el operador de asignación. La última oración es correcta. –

+0

Tiene razón, no es el operador de asignación, sino la conversión implícita de un int. Definitivamente son operadores diferentes, pero al final el efecto es el mismo. Gracias por señalar eso. – rusty

2

La razón de esto es que el compilador crea un operador 'levantado' para los tipos anulables - en este caso, es algo así como:

public static int? operator +(int? a, int? b) 
{ 
    return (a == null || b == null) ? (int?)null : a.Value + b.Value 
} 

Creo que si se intenta asignar el resultado a un no valor nulo, el compilador se verá obligado a utilizar la sobrecarga no nulable y convertir x a un int.

e.g. int i = x + 1; //throws runtime exception 
+0

en realidad int i = x + 1 es un error. int i = (int) (x + 1) lanzará una excepción si x no tiene ningún valor. – Dolphin

0

Independientemente de si x en realidad nunca es nulo, ni siquiera es el punto.

El punto es, ¿cuándo ha visto alguna vez un NullReferenceException al intentar realizar una adición?

El siguiente ejemplo tampoco arroja un NullReferenceException y es perfectamente válido.

string hello = null; 
string world = "world"; 
string hw = hello+world; 

Sólo se conseguiría un NullReferenceException si se intenta acceder a un miembro de un objeto que es nulo.

-1

int? nunca puede ser nulo porque es una estructura. Las estructuras viven en la pila y la pila no maneja bien nula.

Ver What is a NullPointerException, and how do I fix it?

Además, los tipos anulables tienen 2 propiedades muy útiles: HasValue, Valor

este código:

 if (x != null) 
     { 
      return (int) x; 
     } 

caso de que se refactorizado a esto:

 if (x.HasValue) 
     { 
      return x.Value; 
     } 
+0

Esto es completamente incorrecto. Primero, los tipos de valores no "viven en la pila". Los tipos de valor viven donde sea que vivan, ya sea en la pila o en el montón, según lo considere oportuno el administrador de memoria. En segundo lugar, es perfectamente legal tener una referencia nula en la pila. "string s = null;", hay una referencia nula en la pila, no hay problema. –

+1

Aprecio la corrección. Cuando comencé en .NET, recuerdo haber hecho esto: DateTime x = null; y obtener este error "El compilador no puede asignar nulo a un tipo de valor; null solo se puede asignar a un tipo de referencia. struct es un tipo de valor". Yo malentendí el mensaje. El error está hablando de las limitaciones del tipo null-literal y no del tipo de valor. Gracias por la merecida bofetada en la cabeza. – fremis

Cuestiones relacionadas