c# - valor - ¿Por qué se me permite comparar un tipo no anulable con nulo?
system invalidoperationexception no se puede convertir un valor nulo en un tipo de valor (5)
Posible duplicado:
C # está bien con la comparación de tipos de valor a nulo
Si intento asignar null
a un tipo no anulable en C #:
System.DateTime time = null;
Obtendré un error en tiempo de compilación:
error CS0037: no se puede convertir nulo a ''System.DateTime'' porque es un tipo de valor no anulable
lo que tiene sentido Pero si comparamos el mismo tipo con null
:
System.DateTime time = obtainFromSomewhere();
if( time == null ) {
//whatever;
}
no hay error de compilación Esto no tiene sentido para mí: si no puedo asignar null
, ¿por qué alguna vez sería null
?
¿Por qué se me permite comparar un tipo no anulable con null
?
En mi opinión, esto está permitido, porque NULL no es un valor real de ningún tipo.
Es bueno algún código como el siguiente está permitido:
System.DateTime time = obtainFromSomewhere(); // allways a date
System.DateTime? otherTime = obtainFromSomewhereElse(); // null if nothing planned
if (time == otherTime)
{
// match
...
}
¿Qué haríamos sin null de todos modos?
Es debido al Boxing .
DateTime
se puede encuadrar como object
y, por lo tanto, se convierte en una referencia que se puede comparar con null
(aunque siempre será false
).
Sin embargo, un objeto ( null
) no se puede desempaquetar de nuevo en DateTime
, por lo que no se puede asignar a DateTime
.
Ejemplo: podrias hacer
object now = DateTime.Now;
bool isNull = now == null
EDITAR: Como señaló Brian Rasmussen, estaba equivocado con la teoría del boxeo. El boxeo solo se produciría si se lanzara explícitamente a un objeto como en mi ejemplo o en (object)DateTime.Now == null
.
Hay una conversión implícita a un tipo anulable desde .NET 2.0 (vea lo que Eric Lippert dijo aquí ).
El compilador le da la siguiente advertencia que indica que se realiza una conversión:
C:/>c:/windows/Microsoft.NET/Framework/v2.0.50727/csc test.cs Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.4927 for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727 test.cs(16,12): warning CS0464: Comparing with null of type ''int?'' always produces ''false''
En .NET 1.1, que no tenía tipos anulables, su ejemplo de código no habría sido legal:
C:/>c:/windows/Microsoft.NET/Framework/v1.1.4322/csc test.cs Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4 for Microsoft (R) .NET Framework version 1.1.4322 Copyright (C) Microsoft Corporation 2001-2002. All rights reserved. test.cs(12,13): error CS0019: Operator ''=='' cannot be applied to operands of type ''System.DateTime'' and ''''
La razón por la que esto funciona para DateTime
, es porque DateTime
define su propio operador ==
. ¿Porque lo hace, obtiene una versión elevada del operador que se puede usar con DateTime?
. ¿Dado que tanto DateTime
como null
pueden convertirse implícitamente a DateTime?
, la comparación se compila, pero siempre se evaluará como falsa en tiempo de ejecución.
Gracias a Matt Ellen por señalar el hecho de que mi respuesta original no cubrió el ejemplo de la pregunta.
debe ser un tipo anulable
System.DateTime? time = null;
Tu código debería aparecer así:
System.DateTime? time = obtainFromSomewhere();
if( time.HasValue ) {
//use time.Value;
}
pero ¿recuerda que la función obtainFromSomewhere
debería devolver un DateTime?
tipo.