web-dev-qa-db-fra.com

Pourquoi ne puis-je pas vérifier si un "DateTime" est "rien"?

Dans VB.NET, existe-t-il un moyen de définir une variable DateTime sur "non définie"? Et pourquoi est-il possible de définir une DateTime sur Nothing, mais pas de vérifier si elle est Nothing? Par exemple:

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

La deuxième déclaration lève cette erreur:

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

C’est l’une des plus grandes sources de confusion avec VB.Net, IMO.

Nothing en VB.Net est l'équivalent de default(T) en C #: la valeur par défaut pour le type donné.

  • Pour les types de valeur, cela correspond essentiellement à "zéro": 0 pour Integer, False pour Boolean, DateTime.MinValue pour DateTime, ... 
  • Pour les types de référence, il s'agit de la valeur null (une référence qui fait référence à, eh bien, rien).

L'instruction d Is Nothing est donc équivalente à d Is DateTime.MinValue, qui ne compile évidemment pas.

Solutions: comme d'autres l'ont dit

  • Utilisez soit DateTime? (c'est-à-dire Nullable(Of DateTime)). Ceci est ma solution préférée.
  • Ou utilisez d = DateTime.MinValue ou équivalent d = Nothing

Dans le contexte du code original, vous pouvez utiliser:

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

Vous trouverez une explication plus complète sur Le blog de Anthony D. Green

129
jeroenh

DateTime est un type de valeur, raison pour laquelle il ne peut pas être null. Vous pouvez vérifier qu'il est égal à DateTime.MinValue ou vous pouvez utiliser Nullable(Of DateTime) à la place.

VB parfois "utilement" vous fait penser que c'est faire quelque chose que ce n'est pas. Lorsqu'il vous permet de définir une date sur Nothing, il le définit réellement sur une autre valeur, par exemple MinValue.

Voir cette question pour une discussion approfondie des types de valeur par rapport aux types de référence.

10
John M Gant

DateTime est un type value, ce qui signifie qu'il a toujours une valeur. 

C'est comme un entier - ça peut être 0, 1, ou moins que zéro, mais ça ne peut jamais être "rien" 

Si vous voulez un DateTime pouvant prendre la valeur Nothing, utilisez un Nullable DateTime.

3
Cheeso

Quelques exemples sur l’utilisation des valeurs nullable DateTime.

(Voir Types de valeurs nullables (Visual Basic) pour plus d'informations.)

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

En outre, sur la façon de vérifier si une variable est null (à partir de Nothing (Visual Basic) ):

Lorsque vous vérifiez si une variable de référence (ou de type valeur nullable) est null, n'utilisez pas = Nothing ni <> Nothing. Utilisez toujours Is Nothing ou IsNot Nothing.
3
DavidRR

Vous pouvez également utiliser ci-dessous simplement simple à vérifier:

If startDate <> Nothing Then
your logic
End If

Il vérifiera que la variable startDate du type de données DateTime est nulle ou non.

1

Dans n'importe quel langage de programmation, soyez prudent lorsque vous utilisez Nulls. L'exemple ci-dessus montre un autre problème. Si vous utilisez un type Nullable, cela signifie que les variables instanciées à partir de ce type peuvent contenir la valeur System.DBNull.Value; pas qu'il ait changé l'interprétation de la définition de la valeur par défaut à l'aide de "= Nothing" ou que l'objet de la valeur puisse désormais prendre en charge une référence null. Juste un avertissement ... codage heureux!

Vous pouvez créer une classe séparée contenant un type de valeur. Un objet créé à partir d'une telle classe serait un type de référence, auquel on pourrait affecter Nothing. Un exemple:

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

Classe de fin

dans 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

Ensuite, vous pouvez choisir les variables à remplacer pour qu’elles répondent à vos besoins. Beaucoup de travail, mais si vous en avez vraiment besoin, vous pouvez le faire.

1
sscheider

Vous pouvez vérifier ceci comme ci-dessous:

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

Une solution consiste à utiliser le type de données Object à la place:

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

Ensuite, vous pouvez régler la date à rien comme ceci:

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