Почему я не могу проверить, является ли "DateTime" "Nothing"?

В VB.NET существует ли способ установить переменную DateTime в значение "not set"? И почему можно установить DateTime в Nothing, но не удалось проверить, является ли это Nothing? Например:

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

Второй оператор выдает эту ошибку:

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

Ответ 1

Это один из самых больших источников путаницы с VB.Net, IMO.

Nothing в VB.Net является эквивалентом default(T) в С#: значение по умолчанию для данного типа.

  • Для типов значений это по существу эквивалентны нулю: 0 для Integer, False для Boolean, DateTime.MinValue для DateTime,...
  • Для ссылочных типов это значение null (ссылка, которая ссылается, ну, ничего).

Таким образом, утверждение d Is Nothing эквивалентно d Is DateTime.MinValue, которое, очевидно, не компилируется.

Решения: как говорили другие

  • Используйте DateTime? (т.е. Nullable(Of DateTime)). Это мое предпочтительное решение.
  • Или используйте d = DateTime.MinValue или эквивалентно d = Nothing

В контексте исходного кода вы можете использовать:

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

Ответ 2

DateTime - это тип значения, поэтому он не может быть нулевым. Вы можете проверить, чтобы он был равен DateTime.MinValue, или вы можете использовать Nullable(Of DateTime) вместо этого.

VB иногда "помогает" заставляет вас думать, что он что-то делает. Когда он позволяет вам установить дату в "Нет", она действительно устанавливает ее на какое-то другое значение, возможно, MinValue.

См. этот вопрос для подробного обсуждения типов значений по сравнению с ссылочными типами.

Ответ 3

Некоторые примеры работы с значениями с нулевым значением DateTime.

(Подробнее см. 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]

Также, как проверить, является ли переменная null (из Nothing (Visual Basic)):

При проверке того, является ли ссылочная (или нулевая тип типа значения) null, не используйте = Nothing или <> Nothing. Всегда используйте Is Nothing или IsNot Nothing.

Ответ 4

DateTime - это тип значения, что означает, что он всегда имеет некоторое значение.

Это как целое число - оно может быть 0 или 1 или меньше нуля, но никогда не может быть "ничего".

Если вы хотите использовать DateTime, который может принимать значение Nothing, используйте Nullable DateTime.

Ответ 5

На любом языке программирования будьте осторожны при использовании Nulls. В приведенном выше примере показана другая проблема. Если вы используете тип Nullable, это означает, что переменные, созданные из этого типа, могут содержать значение System.DBNull.Value; не то, что он изменил интерпретацию установки значения по умолчанию с помощью "= Nothing" или что объект значения теперь может поддерживать нулевую ссылку. Просто предупреждение... счастливое кодирование!

Вы можете создать отдельный класс, содержащий тип значения. Объект, созданный из такого класса, будет ссылочным типом, которому может быть присвоено Nothing. Пример:

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

Конечный класс

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

Затем вы можете выбрать и переопределить, чтобы сделать то, что вам нужно. Много работы - но если вам это действительно нужно, вы можете это сделать.

Ответ 6

Вы также можете использовать ниже, просто чтобы проверить:

If startDate <> Nothing Then
your logic
End If

Он будет проверять, что переменная startDate типа данных DateTime имеет значение null или нет.

Ответ 7

В этом случае вместо этого следует использовать тип данных Object:

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

Затем вы можете установить дату не так:

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