21

I am trying to set up a date range filter on my UI, with checkboxes to say whether a DateTimePicker's value should be used, e.g.

Dim fromDate As DateTime? = If(fromDatePicker.Checked, fromDatePicker.Value, Nothing)

Yet setting fromDate to Nothing doesn't result in it being set to Nothing but to '12:00:00 AM', and the following If statement incorrectly executes the filter because startDate is not Nothing.

If (Not startDate Is Nothing) Then
    list = list.Where(Function(i) i.InvDate.Value >= startDate.Value)
End If

How do I really ensure startDate gets a value of Nothing?

ProfK
  • 49,207
  • 121
  • 399
  • 775

5 Answers5

30

The issue is that it's examining the right-hand side of this assignment first, and deciding that it is of type DateTime (no ?). Then performing the assignment.

This will work:

Dim fromDate As DateTime? = If(fromDatePicker.Checked, _
                               fromDatePicker.Value, _
                               CType(Nothing, DateTime?))

Because it forces the right-hand side's type to be DateTime?.

As I said in my comment, Nothing can be more akin to C#'s default(T) rather than null:

Nothing represents the default value of a data type. The default value depends on whether the variable is of a value type or of a reference type.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • As you said in your comment as well, "the two are equivalent for reference types", and Nullable(Of DateTime) is a reference type, but it looks like the cast trick works, thanks. – ProfK Sep 26 '12 at 10:19
  • 1
    `Nullable(Of DateTime)` is a reference type. However, at the point in time when `Nothing` was being converted, on the right hand side, we have this type information: `If(Boolean,DateTime,)`. Since the return type of `If` has to match the type of one of its expressions, it picked `DateTime`. It *then* converts `Nothing` to a `DateTime` (creating a default `DateTime`), and only *after* that point does it consider the assignment. – Damien_The_Unbeliever Sep 26 '12 at 10:25
4

With VB.NET and EF 6.X to save null is:

Dim nullableData As New Nullable(Of Date)

danicomas
  • 84
  • 6
  • I think this is an interesting point, though not sure it's exactly answering the original question ;). Where I'm setting a nullable date to null in VB.NET I'm using `nullableData = New Date?`. – Ian Grainger Apr 29 '16 at 09:54
2

In addition to @Damien_The_Unbeliever's fine answer, using New DateTime? also works:

Dim fromDate As DateTime? = If(fromDatePicker.Checked, _
                               fromDatePicker.Value, _
                               New DateTime?)

You might find that it looks a bit counter intuitive, why perhaps the CType(Nothing, DateTime?) is preferable.

Ulf Åkerstedt
  • 3,086
  • 4
  • 26
  • 28
0

Use New Date as a magic number:

Dim fromDate As New Date
If fromDatePicker.Checked Then
  fromDate = fromDatePicker.Value
End If
If fromDate <> New Date Then
  list = list.Where(Function(i) i.InvDate.Value >= fromDate.Value)
End If
SSS
  • 4,807
  • 1
  • 23
  • 44
  • What do you think the difference is between `New Date` and `Nothing` being assigned to a `Date` (or `DateTime`) variable? (hint - there isn't one) – Damien_The_Unbeliever Sep 26 '12 at 06:48
  • More typing: `Dim fromDate As Date = Nothing` – SSS Sep 26 '12 at 06:50
  • `Dim fromDate As Date` is even less typing and has the same observable effects. – Damien_The_Unbeliever Sep 26 '12 at 06:51
  • True enough. However, `fromDate = New Date` is a valid comparison, while `fromDate Is Nothing` is not. So for consistency I would encourage consistent use of `New Date`. I also recommend explicitly setting variables to `Nothing` or `New Date` or `0` or `""` to indicate that the uninitialised value is going to be used as a magic number (and to avoid compiler warnings when you hand them as parameters). It's a style preference I guess - makes no difference at the IL level, as you note. – SSS Sep 26 '12 at 07:01
  • `fromDate = Nothing` is a valid comparison, and uses one less character :-) – Damien_The_Unbeliever Sep 26 '12 at 07:03
  • @SSS Surely we should be moving away from using legacy types/aliases such as `Date`? – ProfK Sep 26 '12 at 10:17
  • I guess that's a style choice too. As I said before, YMMV. – SSS Sep 27 '12 at 01:44
0
        squery = "insert into tblTest values('" & Me.txtCode.Text & "', @Date)"
        Dim cmd = New SqlCommand(squery, con)

        cmd.Parameters.Add("@Date", SqlDbType.DateTime)
        If txtRequireDate.Text = "" Then
            cmd.Parameters("@Date").Value = DBNull.Value
        Else
            cmd.Parameters("@Date").Value = txtRequireDate.Text
        End If
Raj
  • 800
  • 7
  • 8