Why can't I check if a 'DateTime' is &

2019-01-16 09:42发布

问题:

In VB.NET, is there a way to set a DateTime variable to "not set"? And why is it possible to set a DateTime to Nothing, but not possible to check if it is Nothing? For example:

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

The second statement throws this error:

'Is' operator does not accept operands of type 'Date'. Operands must be reference or
nullable types.

回答1:

This is one of the biggest sources of confusion with VB.Net, IMO.

Nothing in VB.Net is the equivalent of default(T) in C#: the default value for the given type.

  • For value types, this is essentially the equivalent of 'zero': 0 for Integer, False for Boolean, DateTime.MinValue for DateTime, ...
  • For reference types, it is the null value (a reference that refers to, well, nothing).

The statement d Is Nothing is therefore equivalent to d Is DateTime.MinValue, which obviously does not compile.

Solutions: as others have said

  • Either use DateTime? (i.e. Nullable(Of DateTime)). This is my preferred solution.
  • Or use d = DateTime.MinValue or equivalently d = Nothing

In the context of the original code, you could use:

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


回答2:

DateTime is a value type, which is why it can't be null. You can check for it to be equal to DateTime.MinValue, or you can use Nullable(Of DateTime) instead.

VB sometimes "helpfully" makes you think it's doing something it's not. When it lets you set a Date to Nothing, it's really setting it to some other value, maybe MinValue.

See this question for an extensive discussion of value types vs. reference types.



回答3:

DateTime is a value type, which means it always has some value.

It's like an integer - it can be 0, or 1, or less than zero, but it can never be "nothing".

If you want a DateTime that can take the value Nothing, use a Nullable DateTime.



回答4:

Some examples on working with nullable DateTime values.

(See Nullable Value Types (Visual Basic) for more.)

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

Also, on how to check whether a variable is null (from Nothing (Visual Basic)):

When checking whether a reference (or nullable value type) variable is null, do not use = Nothing or <> Nothing. Always use Is Nothing or IsNot Nothing.


回答5:

In any programming language, be careful when using Nulls. The example above shows another issue. If you use a type of Nullable, that means that the variables instantiated from that type can hold the value System.DBNull.Value; not that it has changed the interpretation of setting the value to default using "= Nothing" or that the Object of the value can now support a null reference. Just a warning... happy coding!

You could create a separate class containing a value type. An object created from such a class would be a reference type, which could be assigned Nothing. An example:

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

End Class

'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

Then you could pick and choose overridables to make it do what you need. Lot of work - but if you really need it, you can do it.



回答6:

You can also use below just simple to check:

If startDate <> Nothing Then
your logic
End If

It will check that the startDate variable of DateTime datatype is null or not.



回答7:

A way around this would be to use Object datatype instead:

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

Then you can set the date to nothing like so:

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


回答8:

You can check this like below :

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