Why can't I check if a 'DateTime' is 'Nothing'?
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
forInteger
,False
forBoolean
,DateTime.MinValue
forDateTime
, ... - 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 equivalentlyd = Nothing
In the context of the original code, you could use:
Dim d As DateTime? = Nothing
Dim boolNotSet As Boolean = d.HasValue
A more comprehensive explanation can be found on Anthony D. Green's blog
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.
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.
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 useIs Nothing
orIsNot Nothing
.