¿Por qué no puedo verificar si una 'Fecha y hora' es 'Nada'?

81

En VB.NET, ¿hay alguna forma de establecer una DateTimevariable en "no establecida"? ¿Y por qué es posible establecer un DateTimeto Nothing, pero no es posible comprobar si lo es Nothing? Por ejemplo:

Dim d As DateTime = Nothing
Dim boolNotSet As Boolean = d Is Nothing 

La segunda declaración arroja este error:

'Is' operator does not accept operands of type 'Date'. Operands must be reference or
nullable types.
Muleskinner
fuente
1
Además de la respuesta de John Gant a continuación, también puede verificar si la variable de fecha y hora = Nada (tenga en cuenta el = en lugar de "es").
DCNYAM
Gracias, usar Dim boolNotSet As Boolean = d = Nothing parece la solución más simple en este momento. Interesante con el casting que acepta nulos nunca antes visto
Muleskinner
@Chris - Creo que está usando VB
Karthik Ratnam
@Karthik Ratnam, sí, lo es, pero equivale a lo mismo y la respuesta de @Marc Gravell transmite todos los puntos.
Chris Haas
1
@NYSystemsAnalyst: de acuerdo con Nothing (Visual Basic) , usar = Nothingo <> Nothingno es una buena práctica: "Al verificar si una variable de referencia (o un tipo de valor que acepta valores NULL) es nula , no use = Nothingo <> Nothing. Use siempre Is Nothingo IsNot Nothing".
DavidRR

Respuestas:

140

Esta es una de las mayores fuentes de confusión con VB.Net, IMO.

Nothingen VB.Net es el equivalente de default(T)en C #: el valor predeterminado para el tipo dado.

  • Para los tipos de valor, esto es esencialmente el equivalente de 'cero': 0para Integer, Falsepara Boolean, DateTime.MinValuepara DateTime, ...
  • Para los tipos de referencia, es el nullvalor (una referencia que se refiere a, bueno, nada).

Por d Is Nothinglo tanto, la declaración es equivalente a d Is DateTime.MinValue, que obviamente no se compila.

Soluciones: como han dicho otros

  • O use DateTime?(es decir Nullable(Of DateTime)). Esta es mi solución preferida.
  • O use d = DateTime.MinValueo equivalentemented = Nothing

En el contexto del código original, podría usar:

Dim d As DateTime? = Nothing
Dim boolNotSet As Boolean = d.HasValue

Se puede encontrar una explicación más completa en el blog de Anthony D. Green

jeroenh
fuente
1
Gracias por la explicación. Es interesante notar que isNothing (d) no funciona, pero d = ¡Nada funciona!
phn
12

DateTime es un tipo de valor, por lo que no puede ser nulo. Puede verificar que sea igual a DateTime.MinValue, o puede usar Nullable(Of DateTime)en su lugar.

VB a veces "amablemente" te hace pensar que está haciendo algo que no está haciendo. Cuando le permite establecer una Fecha en Nada, realmente lo está estableciendo en algún otro valor, tal vez MinValue.

Consulte esta pregunta para obtener una explicación detallada de los tipos de valor frente a los tipos de referencia.

John M. Gant
fuente
4

DateTime es un tipo de valor , lo que significa que siempre tiene algún valor.

Es como un número entero: puede ser 0, 1 o menos de cero, pero nunca puede ser "nada".

Si desea un DateTime que pueda tomar el valor Nothing, use un DateTime anulable.

Cheeso
fuente
4

Algunos ejemplos sobre cómo trabajar con DateTimevalores que aceptan valores NULL .

(Consulte Tipos de valor que aceptan valores NULL (Visual Basic) para obtener más información).

'
' An ordinary DateTime declaration. It is *not* nullable. Setting it to
' 'Nothing' actually results in a non-null value.
'
Dim d1 As DateTime = Nothing
Console.WriteLine(String.Format("d1 = [{0}]\n", d1))
' Output:  d1 = [1/1/0001 12:00:00 AM]

' Console.WriteLine(String.Format("d1 is Nothing? [{0}]\n", (d1 Is Nothing)))
'
'   Compilation error on above expression '(d1 Is Nothing)':
'
'      'Is' operator does not accept operands of type 'Date'.
'       Operands must be reference or nullable types.

'
' Three different but equivalent ways to declare a DateTime
' nullable:
'
Dim d2? As DateTime = Nothing
Console.WriteLine(String.Format("d2 = [{0}][{1}]\n", d2, (d2 Is Nothing)))
' Output:  d2 = [][True]

Dim d3 As DateTime? = Nothing
Console.WriteLine(String.Format("d3 = [{0}][{1}]\n", d3, (d3 Is Nothing)))
' Output:  d3 = [][True]

Dim d4 As Nullable(Of DateTime) = Nothing
Console.WriteLine(String.Format("d4 = [{0}][{1}]\n", d4, (d4 Is Nothing)))
' Output:  d4 = [][True]

Además, sobre cómo verificar si una variable es nula (de Nothing (Visual Basic) ):

Al verificar si una variable de referencia (o tipo de valor que acepta valores NULL) es nula , no use = Nothingo <> Nothing. Utilice siempre Is Nothingo IsNot Nothing.
DavidRR
fuente
1

En cualquier lenguaje de programación, tenga cuidado al usar Nulls. El ejemplo anterior muestra otro problema. Si usa un tipo de Nullable, eso significa que las variables instanciadas de ese tipo pueden tener el valor System.DBNull.Value; no es que haya cambiado la interpretación de establecer el valor por defecto usando "= Nada" o que el Objeto del valor ahora pueda admitir una referencia nula. Solo una advertencia ... ¡feliz codificación!

Puede crear una clase separada que contenga un tipo de valor. Un objeto creado a partir de dicha clase sería un tipo de referencia, al que se le podría asignar Nothing. Un ejemplo:

Public Class DateTimeNullable
Private _value As DateTime

'properties
Public Property Value() As DateTime
    Get
        Return _value
    End Get
    Set(ByVal value As DateTime)
        _value = value
    End Set
End Property

'constructors
Public Sub New()
    Value = DateTime.MinValue
End Sub

Public Sub New(ByVal dt As DateTime)
    Value = dt
End Sub

'overridables
Public Overrides Function ToString() As String
    Return Value.ToString()
End Function

Clase final

'en Main ():

        Dim dtn As DateTimeNullable = Nothing
    Dim strTest1 As String = "Falied"
    Dim strTest2 As String = "Failed"
    If dtn Is Nothing Then strTest1 = "Succeeded"

    dtn = New DateTimeNullable(DateTime.Now)
    If dtn Is Nothing Then strTest2 = "Succeeded"

    Console.WriteLine("test1: " & strTest1)
    Console.WriteLine("test2: " & strTest2)
    Console.WriteLine(".ToString() = " & dtn.ToString())
    Console.WriteLine(".Value.ToString() = " & dtn.Value.ToString())

    Console.ReadKey()

    ' Output:
    'test1:  Succeeded()
    'test2:  Failed()
    '.ToString() = 4/10/2012 11:28:10 AM
    '.Value.ToString() = 4/10/2012 11:28:10 AM

Luego, puede elegir anulables para que haga lo que necesita. Mucho trabajo, pero si realmente lo necesita, puede hacerlo.

sscheider
fuente
1

También puede usar a continuación simplemente para verificar:

If startDate <> Nothing Then
your logic
End If

Verificará que la variable startDate del tipo de datos DateTime sea nula o no.

Mahavirsinh Padhiyar
fuente
1

Puede comprobar esto como a continuación:

if varDate = "#01/01/0001#" then
       '  blank date. do something.
else
       ' Date is not blank. Do some other thing
end if
Sukhi
fuente
0

Una forma de evitar esto sería usar el tipo de datos Object en su lugar:

Private _myDate As Object
Private Property MyDate As Date
    Get
        If IsNothing(_myDate) Then Return Nothing
        Return CDate(_myDate)
    End Get
    Set(value As Date)
        If date = Nothing Then
            _myDate = Nothing
            Return
        End If
        _myDate = value
     End Set
End Property

Entonces puede establecer la fecha en nada parecido a esto:

MyDate = Nothing
Dim theDate As Date = MyDate
If theDate = Nothing Then
    'date is nothing
End If
George Filippakos
fuente