valores valor utilice tipos tipo son qué que puede nulos nulo los datos convertir anulables acepte aceptar c# .net nullable non-nullable

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.