¿Por qué no puedo verificar si una 'fecha de fecha' no es 'nada'?
Pregunta
En vb.net, ¿hay alguna forma de establecer un DateTime
variable a "no establecer"? ¿Y por qué es posible establecer un DateTime
a Nothing
, pero no posible verificar si 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.
Solución
Esta es una de las mayores fuentes de confusión con VB.NET, IMO.
Nothing
en vb.net es el equivalente de default(T)
En C#: el valor predeterminado para el tipo dado.
- Para los tipos de valor, este es esencialmente el equivalente de 'cero':
0
porInteger
,False
porBoolean
,DateTime.MinValue
porDateTime
, ... - Para los tipos de referencia, es el
null
valor (una referencia que se refiere a, bueno, nada).
La declaración d Is Nothing
Por lo tanto, es equivalente a d Is DateTime.MinValue
, que obviamente no se compila.
Soluciones: como otros han dicho
- Ya sea
DateTime?
(es decirNullable(Of DateTime)
). Esta es mi solución preferida. - O usar
d = DateTime.MinValue
o equivalented = Nothing
En el contexto del código original, puede usar:
Dim d As DateTime? = Nothing
Dim boolNotSet As Boolean = d.HasValue
Una explicación más completa se puede encontrar en Blog de Anthony D. Green
Otros consejos
DateTime es un tipo de valor, por lo que no puede ser nulo. Puede verificar que sea igual a DateTime.MinValue
, o puedes usar Nullable(Of DateTime)
en cambio.
VB a veces "útilmente" te hace pensar que está haciendo algo que no es. Cuando le permite establecer una fecha en nada, realmente lo está estableciendo en algún otro valor, tal vez minvalue.
Ver esta pregunta Para una amplia discusión de tipos de valor versus tipos de referencia.
DateTime es un tipo de valor, lo que significa que siempre tiene algún valor.
Es como un entero: puede ser 0, o 1 o menos de cero, pero nunca puede ser "nada".
Si desea una fecha de detección que no pueda tomar el valor nada, use una fecha de fecha anulable.
Algunos ejemplos sobre trabajar con anulable DateTime
valores.
(Ver Tipos de valor anulables (Visual Basic) para más.)
'
' 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 nulo (de Nada (Visual Basic)):
Al verificar si una variable de referencia (o tipo de valor anulable) es nulo, no utilice= Nothing
o<> Nothing
. Siempre usaIs Nothing
oIsNot Nothing
.
En cualquier lenguaje de programación, tenga cuidado cuando use nulos. El ejemplo anterior muestra otro problema. Si usa un tipo de anulable, eso significa que las variables instanciadas desde ese tipo pueden contener el valor System.dbnull.value; No es que haya cambiado la interpretación de establecer el valor en el valor predeterminado usando "= nada" o que el objeto del valor ahora puede 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, que no se le podría asignar nada. 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 y elegir Inveridables para que haga lo que necesita. Mucho trabajo, pero si realmente lo necesitas, puedes hacerlo.
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 de DateTime sea nula o no.
Puede verificar 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
Una forma de evitar esto sería usar el tipo de datos de objetos: 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 puedes establecer la fecha en nada como:
MyDate = Nothing
Dim theDate As Date = MyDate
If theDate = Nothing Then
'date is nothing
End If