Tại sao tôi không thể kiểm tra xem 'DateTime' có phải là 'Không có gì' không?


81

Trong VB.NET, có cách nào để đặt một DateTimebiến thành "not set" không? Và tại sao là nó có thể để thiết lập một DateTimeđến Nothing, nhưng không thể kiểm tra xem nó là Nothing? Ví dụ:

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

Câu lệnh thứ hai đưa ra lỗi này:

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

1
Ngoài câu trả lời của John Gant bên dưới, bạn cũng có thể kiểm tra xem biến datetime có = Không (Lưu ý dấu = thay vì "là").
DCNYAM

Cảm ơn, sử dụng Dim boolNotSet As Boolean = d = Không có gì có vẻ là giải pháp đơn giản nhất hiện nay. Thú vị với dàn cast Nullable chưa từng thấy trước đây
Muleskinner

@Chris - Tôi nghĩ Anh ấy đang sử dụng VB
Karthik Ratnam,

@Karthik Ratnam, đúng là như vậy nhưng nó cũng giống nhau và câu trả lời của @Marc Gravell cho thấy tất cả các điểm.
Chris Haas

1
@NYSystemsAnalyst: theo Không có gì (Visual Basic) , sử dụng = Nothinghoặc <> Nothingkhông thực hiện tốt: "Khi kiểm tra xem biến tham chiếu (hoặc kiểu giá trị nullable) có rỗng hay không , không sử dụng = Nothinghoặc <> Nothing. Luôn sử dụng Is Nothinghoặc IsNot Nothing."
DavidRR

Câu trả lời:


140

Đây là một trong những nguồn gây nhầm lẫn lớn nhất với VB.Net, IMO.

Nothing trong VB.Net tương đương với default(T) trong C #: giá trị mặc định cho kiểu đã cho.

  • Đối với các loại giá trị, điều này về cơ bản tương đương với '0': 0for Integer, Falsefor Boolean,DateTime.MinValue for DateTime, ...
  • Đối với các loại tham chiếu, nó là nullgiá trị (tham chiếu đề cập đến, tốt, không có gì).

d Is NothingDo đó, câu lệnh tương đương với d Is DateTime.MinValue, rõ ràng là không biên dịch.

Giải pháp: như những người khác đã nói

  • Hoặc sử dụng DateTime?(tức là Nullable(Of DateTime)). Đây là giải pháp ưa thích của tôi.
  • Hoặc sử dụng d = DateTime.MinValuehoặc tương đươngd = Nothing

Trong ngữ cảnh của mã gốc, bạn có thể sử dụng:

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

Một lời giải thích toàn diện hơn có thể được tìm thấy trên blog của Anthony D. Green


1
Cảm ơn vì đã giải thích. Có một điều thú vị là isNothing (d) không hoạt động nhưng d = Không có gì cả!
phn

12

DateTime là một kiểu giá trị, đó là lý do tại sao nó không thể rỗng. Bạn có thể kiểm tra xem nó bằng DateTime.MinValuehoặc bạn có thể sử dụng Nullable(Of DateTime)thay thế.

VB đôi khi "hữu ích" làm cho bạn nghĩ rằng nó đang làm một cái gì đó không phải. Khi nó cho phép bạn đặt Ngày thành Không, nó thực sự đang đặt nó thành một số giá trị khác, có thể là MinValue.

Xem câu hỏi này để biết thảo luận sâu rộng về các loại giá trị so với các loại tham chiếu.


4

DateTime là một kiểu giá trị , có nghĩa là nó luôn có một số giá trị.

Nó giống như một số nguyên - nó có thể là 0, 1, hoặc nhỏ hơn 0, nhưng nó không bao giờ có thể là "không có gì".

Nếu bạn muốn DateTime có thể nhận giá trị Không có gì, hãy sử dụng Nullable DateTime.


4

Một số ví dụ về cách làm việc với DateTimegiá trị nullable .

(Xem Các loại giá trị vô hiệu (Visual Basic) để biết thêm.)

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

Ngoài ra, về cách kiểm tra xem một biến có rỗng hay không (từ Không có gì (Visual Basic) ):

Khi kiểm tra xem một biến tham chiếu (hoặc kiểu giá trị nullable) có rỗng hay không , không sử dụng = Nothinghoặc <> Nothing. Luôn sử dụng Is Nothinghoặc IsNot Nothing.

1

Trong bất kỳ ngôn ngữ lập trình nào, hãy cẩn thận khi sử dụng Nulls. Ví dụ trên cho thấy một vấn đề khác. Nếu bạn sử dụng một kiểu Nullable, điều đó có nghĩa là các biến được khởi tạo từ kiểu đó có thể giữ giá trị System.DBNull.Value; không phải là nó đã thay đổi cách diễn giải của việc đặt giá trị thành mặc định bằng cách sử dụng "= Không có gì" hoặc Đối tượng của giá trị hiện có thể hỗ trợ một tham chiếu rỗng. Chỉ là một cảnh báo ... mã hóa vui vẻ!

Bạn có thể tạo một lớp riêng biệt chứa một kiểu giá trị. Một đối tượng được tạo từ một lớp như vậy sẽ là một kiểu tham chiếu, có thể được gán Không có gì. Một ví dụ:

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

Kết thúc lớp học

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

Sau đó, bạn có thể chọn và chọn các mục ghi đè để làm cho nó thực hiện những gì bạn cần. Rất nhiều việc - nhưng nếu bạn thực sự cần, bạn có thể làm được.


1

Bạn cũng có thể sử dụng bên dưới chỉ đơn giản để kiểm tra:

If startDate <> Nothing Then
your logic
End If

Nó sẽ kiểm tra xem biến startDate của kiểu dữ liệu DateTime có rỗng hay không.


1

Bạn có thể kiểm tra điều này như dưới đây:

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

0

Một cách giải quyết vấn đề này là sử dụng kiểu dữ liệu Object thay thế:

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

Sau đó, bạn có thể đặt ngày không giống như vậy:

MyDate = Nothing
Dim theDate As Date = MyDate
If theDate = Nothing Then
    'date is nothing
End If
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.