Warum kann ich nicht überprüfen, ob eine "DateTime" "Nothing" ist?

81

Gibt es in VB.NET eine Möglichkeit, eine DateTimeVariable auf "nicht gesetzt" zu setzen? Und warum ist es möglich, ein DateTimezu setzen Nothing, aber nicht zu überprüfen, ob es ist Nothing? Zum Beispiel:

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

Die zweite Anweisung löst diesen Fehler aus:

'Is' operator does not accept operands of type 'Date'. Operands must be reference or
nullable types.
Muleskinner
quelle
1
Zusätzlich zu der Antwort von John Gant unten können Sie auch überprüfen, ob die datetime-Variable = Nothing ist (Beachten Sie das = anstelle von "is").
DCNYAM
Vielen Dank, Dim boolNotSet As Boolean = d = verwenden. Nichts scheint derzeit die einfachste Lösung zu sein. Interessant mit dem Nullable Casting, das ich noch nie gesehen habe
Muleskinner
@ Chris - Ich denke, er verwendet VB
Karthik Ratnam
@Karthik Ratnam, ja, das ist er, aber es läuft auf dasselbe hinaus und @Marc Gravells Antwort bringt alle Punkte auf den Punkt.
Chris Haas
1
@NYSystemsAnalyst: nach Nothing (Visual Basic) , mit = Nothingoder <> Nothingist keine gute Praxis: „Bei der Prüfung , ob eine Referenz (oder Nullable - Wertetyp) Variable ist null , nicht verwenden = Nothingoder <> Nothingverwenden Sie immer. Is NothingOder IsNot Nothing.“
DavidRR

Antworten:

140

Dies ist eine der größten Verwechslungsquellen mit VB.Net, IMO.

Nothingin VB.Net entspricht default(T)in C #: dem Standardwert für den angegebenen Typ.

  • Für Werttypen ist dies im Wesentlichen das Äquivalent von 'Null': 0für Integer, Falsefür Boolean, DateTime.MinValuefür DateTime, ...
  • Bei Referenztypen ist dies der nullWert (eine Referenz, die sich auf nichts bezieht).

Die Aussage d Is Nothingist daher äquivalent zu d Is DateTime.MinValue, was offensichtlich nicht kompiliert wird.

Lösungen: wie andere gesagt haben

  • Verwenden Sie entweder DateTime?(dh Nullable(Of DateTime)). Dies ist meine bevorzugte Lösung.
  • Oder verwenden d = DateTime.MinValueoder gleichwertigd = Nothing

Im Kontext des Originalcodes können Sie Folgendes verwenden:

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

Eine umfassendere Erklärung finden Sie im Blog von Anthony D. Green

jeroenh
quelle
1
Danke für die Erklärung. Es ist interessant festzustellen, dass isNothing (d) nicht funktioniert, aber d = Nothing!
Phn
12

DateTime ist ein Werttyp, weshalb er nicht null sein kann. Sie können überprüfen, ob es gleich ist DateTime.MinValue, oder Sie können Nullable(Of DateTime)stattdessen verwenden.

VB lässt Sie manchmal "hilfreich" denken, dass es etwas tut, was es nicht ist. Wenn Sie ein Datum auf Nichts setzen können, wird es wirklich auf einen anderen Wert gesetzt, z. B. MinValue.

In dieser Frage finden Sie eine ausführliche Beschreibung der Werttypen im Vergleich zu den Referenztypen.

John M Gant
quelle
4

Datetime ist ein Werttyp , die es bedeutet immer einen gewissen Wert hat.

Es ist wie eine ganze Zahl - es kann 0 oder 1 oder weniger als Null sein, aber es kann niemals "nichts" sein.

Wenn Sie eine DateTime möchten, die den Wert Nothing annehmen kann, verwenden Sie eine nullable DateTime.

Cheeso
quelle
4

Einige Beispiele zum Arbeiten mit nullbaren DateTimeWerten.

(Weitere Informationen finden Sie unter Nullable Value Types (Visual Basic) .)

'
' 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]

Außerdem erfahren Sie, wie Sie überprüfen, ob eine Variable null ist (von Nothing (Visual Basic) ):

Verwenden Sie oder nicht, wenn Sie überprüfen, ob eine Referenzvariable (oder ein Werttyp mit nullwert) null ist . Verwenden Sie immer oder . = Nothing<> NothingIs NothingIsNot Nothing
DavidRR
quelle
1

Seien Sie in jeder Programmiersprache vorsichtig, wenn Sie Nullen verwenden. Das obige Beispiel zeigt ein anderes Problem. Wenn Sie einen Typ von Nullable verwenden, bedeutet dies, dass die von diesem Typ instanziierten Variablen den Wert System.DBNull.Value enthalten können. nicht, dass es die Interpretation geändert hat, den Wert mit "= Nothing" auf den Standardwert zu setzen, oder dass das Objekt des Werts jetzt eine Nullreferenz unterstützen kann. Nur eine Warnung ... viel Spaß beim Codieren!

Sie können eine separate Klasse erstellen, die einen Werttyp enthält. Ein aus einer solchen Klasse erstelltes Objekt wäre ein Referenztyp, dem Nothing zugewiesen werden könnte. Ein Beispiel:

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

Klasse beenden

'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

Dann können Sie Overridables auswählen, damit es das tut, was Sie brauchen. Viel Arbeit - aber wenn Sie es wirklich brauchen, können Sie es tun.

sscheider
quelle
1

Sie können auch unten einfach zu überprüfen verwenden:

If startDate <> Nothing Then
your logic
End If

Es wird überprüft, ob die Variable startDate des Datentyps DateTime null ist oder nicht.

Mahavirsinh Padhiyar
quelle
1

Sie können dies wie folgt überprüfen:

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

Eine Möglichkeit, dies zu umgehen, besteht darin, stattdessen den Objektdatentyp zu verwenden:

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

Dann können Sie das Datum so einstellen:

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