Perché non posso verificare se un "datetime" è "niente"?
Domanda
In vb.net, c'è un modo per impostare un DateTime
variabile a "non impostato"? E perché è possibile impostare un DateTime
a Nothing
, ma non possibile verificare se lo è Nothing
? Per esempio:
Dim d As DateTime = Nothing
Dim boolNotSet As Boolean = d Is Nothing
La seconda affermazione lancia questo errore:
'Is' operator does not accept operands of type 'Date'. Operands must be reference or
nullable types.
Soluzione
Questa è una delle maggiori fonti di confusione con VB.NET, IMO.
Nothing
in vb.net è l'equivalente di default(T)
In C#: il valore predefinito per il tipo dato.
- Per i tipi di valore, questo è essenzialmente l'equivalente di "zero":
0
perInteger
,False
perBoolean
,DateTime.MinValue
perDateTime
, ... - Per i tipi di riferimento, è il
null
valore (un riferimento che si riferisce, beh, nulla).
La dichiarazione d Is Nothing
è quindi equivalente a d Is DateTime.MinValue
, che ovviamente non si compila.
Soluzioni: come altri hanno detto
- O usare
DateTime?
(cioèNullable(Of DateTime)
). Questa è la mia soluzione preferita. - O usare
d = DateTime.MinValue
o equivalentemented = Nothing
Nel contesto del codice originale, potresti usare:
Dim d As DateTime? = Nothing
Dim boolNotSet As Boolean = d.HasValue
Una spiegazione più completa può essere trovata su Il blog di Anthony D. Green
Altri suggerimenti
DateTime è un tipo di valore, motivo per cui non può essere nullo. Puoi verificare che sia uguale a DateTime.MinValue
, o puoi usare Nullable(Of DateTime)
invece.
VB a volte "utile" ti fa pensare che stia facendo qualcosa che non è. Quando ti consente di impostare una data su nulla, lo sta davvero impostando su qualche altro valore, forse Minvalue.
Vedere questa domanda Per una vasta discussione sui tipi di valore rispetto ai tipi di riferimento.
DateTime è a Tipo di valore, il che significa che ha sempre un certo valore.
È come un numero intero: può essere 0, o 1 o meno di zero, ma non può mai essere "niente".
Se si desidera un DateTime in grado di non prendere il valore, utilizzare un Nulllable DateTime.
Alcuni esempi su come lavorare con Nullable DateTime
i valori.
(Vedere Tipi di valore nulli (Visual Basic) per più.)
'
' 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]
Inoltre, su come verificare se una variabile è nullo (da Niente (Visual Basic)):
Quando si verifica se una variabile di riferimento (o tipo di valore nullo) è nullo, non usare= Nothing
o<> Nothing
. Usa sempreIs Nothing
oIsNot Nothing
.
In qualsiasi linguaggio di programmazione, fai attenzione quando si utilizza nulls. L'esempio sopra mostra un altro problema. Se si utilizza un tipo di nullable, ciò significa che le variabili istanziate da quel tipo possono contenere il valori System.dbnull.value; Non che abbia cambiato l'interpretazione dell'impostazione del valore in default usando "= nulla" o che l'oggetto del valore può ora supportare un riferimento nullo. Solo un avvertimento ... Happy Coding!
È possibile creare una classe separata contenente un tipo di valore. Un oggetto creato da tale classe sarebbe un tipo di riferimento, che non potrebbe essere assegnato nulla. Un esempio:
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
Classe di fine
'In 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
Quindi potresti scegliere i sovraccarichi per farlo fare ciò di cui hai bisogno. Molto lavoro - ma se ne hai davvero bisogno, puoi farlo.
Puoi anche usare di seguito semplicemente semplice da controllare:
If startDate <> Nothing Then
your logic
End If
Verificherà che la variabile StartDate di DataType DateTime sia nulla o meno.
Puoi controllare questo come sotto:
if varDate = "#01/01/0001#" then
' blank date. do something.
else
' Date is not blank. Do some other thing
end if
Un modo per aggirare questo sarebbe quello di utilizzare il tipo di dati oggetto invece:
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
Quindi puoi impostare la data su niente del genere:
MyDate = Nothing
Dim theDate As Date = MyDate
If theDate = Nothing Then
'date is nothing
End If