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.