Чому я не можу перевірити, чи є "DateTime" "Нічого"?


81

У VB.NET чи існує спосіб встановити для DateTimeзмінної значення "не встановлено"? І чому можна встановити 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
На додаток до відповіді Джона Ганта нижче, ви також можете перевірити, чи змінна datetime = Нічого (зверніть увагу на = замість "є").
DCNYAM

Дякуємо, використовуючи Dim boolNotSet As Boolean = d = Ніщо зараз не здається найпростішим рішенням. Цікавий кастинг Nullable, якого ніколи раніше не бачив
Мулескіннер,

@Chris - Я думаю, що він використовує VB
Картік Ратнам

@Karthik Ratnam, так він є, але це те саме, і відповідь @Marc Gravell отримує всі пункти.
Кріс Хаас,

1
@NYSystemsAnalyst: згідно з нічим (Visual Basic) , використання = Nothingабо <> Nothingне є доброю практикою: "Під час перевірки, чи є посилальна (або типовим значенням значення) змінна нульовою , не використовуйте = Nothingабо <> Nothing. Завжди використовуйте Is Nothingабо IsNot Nothing."
DavidRR

Відповіді:


140

Це одне з найбільших джерел плутанини з VB.Net, IMO.

Nothingу VB.Net є еквівалентом default(T)у C #: значення за замовчуванням для даного типу.

  • Для типів значень це, по суті, еквівалент "нуля": 0for Integer, Falsefor Boolean, DateTime.MinValuefor 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

Більш вичерпне пояснення можна знайти в блозі Ентоні Д. Гріна


1
Дякую за пояснення. Цікаво відзначити, що isNothing (d) не працює, але d = Нічого не працює!
пн

12

DateTime - це тип значення, саме тому він не може бути нульовим. Ви можете перевірити DateTime.MinValue, чи дорівнює він , або Nullable(Of DateTime)замість цього використовувати .

VB іноді "корисно" змушує вас думати, що він робить те, що не робить. Коли це дозволяє вам встановити для дати значення Нічого, це насправді встановлює якесь інше значення, можливо, MinValue.

Див. Це запитання для розгорнутого обговорення типів значень проти типів посилань.


4

DateTime - це тип значення , що означає, що він завжди має якесь значення.

Це як ціле число - воно може бути 0, або 1, або менше нуля, але ніколи не може бути "нічим".

Якщо вам потрібен DateTime, який може приймати значення Nothing, використовуйте Nullable DateTime.


4

Кілька прикладів роботи з DateTimeзначеннями, що допускають обнулення .

(Докладніше див. У розділі Типи значень, що допускають відхилення (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]

Крім того, про те, як перевірити, чи є змінна нульовоюНічого (Visual Basic) ):

При перевірці змінна посилання (або обнуляє тип значення) є нульовим , не використовують = Nothingабо <> Nothing. Завжди використовуйте Is Nothingабо IsNot Nothing.

1

Будь-якою мовою програмування будьте обережні, використовуючи Nulls. У наведеному вище прикладі показано інше питання. Якщо ви використовуєте тип Nullable, це означає, що змінні, створені з цього типу, можуть містити значення System.DBNull.Value; не те, що воно змінило інтерпретацію встановлення значення за замовчуванням за допомогою "= Нічого" або що Об'єкт значення тепер може підтримувати нульове посилання. Просто попередження ... щасливого кодування!

Ви можете створити окремий клас, що містить тип значення. Об'єкт, створений з такого класу, буде посилальним типом, якому можна присвоїти Нічого. Приклад:

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

Кінцевий клас

'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

Тоді ви можете вибрати і переорієнтувати, щоб зробити це, що вам потрібно. Багато роботи - але якщо вона вам дійсно потрібна, ви можете це зробити.


1

Ви також можете використовувати нижче, щоб просто перевірити:

If startDate <> Nothing Then
your logic
End If

Він перевірить, чи є змінна startDate типу даних DateTime нульовою чи ні.


1

Ви можете перевірити це, як показано нижче:

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

0

Для цього можна було б використовувати тип даних 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.