Vérification pour voir si une variable DateTime a une valeur attribuée

131

Existe-t-il un moyen simple dans C # de vérifier si une instance de DateTime a reçu une valeur ou non?

Meuglement
la source

Réponses:

83

La seule façon d'avoir une variable à laquelle aucune valeur n'a été attribuée en C # est qu'elle soit une variable locale - auquel cas, au moment de la compilation, vous pouvez dire qu'elle n'est pas définitivement affectée en essayant de lire à partir d'elle: )

Je soupçonne que vous voulez vraiment Nullable<DateTime>(ou DateTime?avec le sucre syntaxique C #) - faites-le nullpour commencer, puis attribuez une DateTimevaleur normale (qui sera convertie de manière appropriée). Ensuite, vous pouvez simplement comparer avec null(ou utiliser la HasValuepropriété) pour voir si une valeur "réelle" a été définie.

Jon Skeet
la source
que diriez-vous de vérifier si la valeur est égale à la valeur datetime par défaut. Y a-t-il un inconvénient imperceptible à cette approche? if (request.StartDateTime == default (DateTime) {request.StartDateTime = DateTime.Now;}
Menol
8
@Menol: Eh bien, cela ne fait pas la différence entre un champ qui a délibérément reçu une valeur de default(DateTime)et un autre qui était juste comme ça au départ. En gros, il traite une valeur du domaine comme "spéciale et indisponible pour une utilisation normale", ce que je n'aime pas.
Jon Skeet
298

voulez-vous dire comme ça:

DateTime datetime = new DateTime();

if (datetime == DateTime.MinValue)
{
    //unassigned
}

ou vous pouvez utiliser Nullable

DateTime? datetime = null;

 if (!datetime.HasValue)
 {
     //unassigned
 }
Hath
la source
5
Seul le second est à l'épreuve des balles. Le premier suppose quelque chose à propos de la représentation non définie d'un DateTime qui n'est pas garantie par le framework. Personnellement, je pense qu'ils auraient dû ajouter un membre statique Unset pour ce scénario.
Rupert Rawnsley
18
Pour ajouter ce que @RupertRawnsley a dit, vous devez en fait comparer avec default (DateTime), qui est la valeur d'un DateTime non attribué. Il se trouve qu'il est juste égal à MinValue, mais cela pourrait changer.
Tsahi Asher
32

mettez ceci quelque part:

public static class DateTimeUtil //or whatever name
{
    public static bool IsEmpty(this DateTime dateTime)
    {
        return dateTime == default(DateTime);
    }
}

puis:

DateTime datetime = ...;

if (datetime.IsEmpty())
{
    //unassigned
}
sonatique
la source
J'aime cette idée, mais notez que dans le cas quelque peu improbable où la variable DateTime se voit attribuer une valeur qui se trouve être la valeur par défaut, cette méthode d'extension renverra le mauvais résultat. Le seul moyen d'éviter cela est d'utiliser un DateTime nullable, ce qui a déjà été suggéré. J'aime toujours beaucoup (et j'utilise maintenant) votre réponse, merci!
Klicker le
@Klicker: Merci pour votre gentil commentaire, mais je ne suis pas sûr de comprendre votre remarque. Pour autant que je sache, == dans ce cas retournera toujours true lorsque datetime est équivalent à default (DateTime) quelle que soit la manière dont la valeur par défaut est attribuée à datetime. Laissez-moi vous expliquer: en fait, le deuxième extrait de ma réponse est faux, il ne se compilera pas, car si vous considérez que c'est le corps d'une fonction, alors datetime n'est pas attribué et le compilateur refusera de l'utiliser. Vous devrez donc lui attribuer une valeur. Il peut s'agir directement ou indirectement de la valeur par défaut (DateTime). Je modifierai ma réponse.
sonatique
et si dans un autre contexte datetime est membre d'une classe, et qu'il est laissé tel quel, le runtime lui attribuera par défaut (DateTime). Le == pour les structures compare en fait le contenu de la structure, quelle que soit la façon dont la structure finit par être remplie avec ce contenu.
sonatique
Mon point ne concerne vraiment que les membres de la classe, et ce que je veux dire, c'est; si vous avez un champ ou une propriété DateTime de niveau classe auquel vous avez assigné MinValue, votre IsEmptyméthode retournera true, ce qui n'est probablement pas ce que vous voudriez (car il n'est pas vide - la valeur par défaut lui a été attribuée). Je suppose que le nom de votre méthode serait plus adapté que IsDefaultValue. Puisque vous ne pouvez pas vraiment avoir un DateTime non nullable IsEmpty.
Klicker
@Klicker: ah oui, OK, compris. Vous avez raison: le nom que j'ai choisi est trompeur. IsDefaultValueaurait été mieux
sonatique
5

DateTime est un type valeur, il ne peut donc jamais être nul. Si vous pensez à DateTime? (Nullable) vous pouvez utiliser:

DateTime? something = GetDateTime();
bool isNull = (something == null);
bool isNull2 = !something.HasValue;
TcKs
la source
5

Je viens de découvrir que GetHashCode () pour une date / heure non attribuée est toujours zéro. Je ne suis pas sûr que ce soit un bon moyen de vérifier la date / heure nulle, car je ne trouve aucune documentation sur la raison pour laquelle ce comportement est affiché.

if(dt.GetHashCode()==0)
{
    Console.WriteLine("DateTime is unassigned"); 
} 
Arcturus
la source
1
GetHashCode0 rendements en raison de tiques (de représentation interne de DateTime) sont aussi égaux à 0. code de hachage calculé par la façon suivante: unchecked((int)ticks) ^ (int)(ticks >> 32);. Voir aussi ici: referencesource.microsoft.com/#mscorlib/system/datetime.cs,836
Ivan Kochurkin
Merci beaucoup. J'essaie de sérialiser un fichier XML à partir d'une classe C # et d'exclure les attributs nuls. Cela a aidé.
Jim Neff
5

Utilisez Nullable<DateTime>si possible.

baretta
la source
3

Je dirais que la valeur par défaut est toujours new DateTime(). Pour que nous puissions écrire

DateTime datetime;

if (datetime == new DateTime())
{
    //unassigned
}
Sabine
la source
2
Cette solution a déjà été donnée par + Hath en 2008 et, comme l'a ajouté + Rupert Rawnsley en commentaire, n'est pas à l'épreuve des balles ...
Roland Bär
0

Je préfère généralement, lorsque cela est possible, utiliser la valeur par défaut des types valeur pour déterminer s'ils ont été définis. Ce n'est évidemment pas possible tout le temps, en particulier avec ints - mais pour DateTimes, je pense que réserver la MinValue pour signifier qu'elle n'a pas été modifiée est assez juste. L'avantage de ceci par rapport aux nullables est qu'il y a un endroit en moins où vous obtiendrez une exception de référence nulle (et probablement beaucoup d'endroits où vous n'avez pas à vérifier null avant d'y accéder!)

Steve Dunn
la source
0

Si vous ne voulez pas avoir à vous soucier des problèmes de valeur Null comme la vérification de la valeur null à chaque fois que vous l'utilisez ou de l'encapsuler dans une logique, et que vous ne voulez pas non plus avoir à vous soucier des problèmes de temps de décalage, alors c'est comment j'ai résolu le problème:

startDate = startDate < DateTime.MinValue.AddDays(1) ? keepIt : resetIt

Je vérifie juste que la valeur par défaut est inférieure à un jour après le début de l'heure. Fonctionne comme un charme.

Urasquirrel
la source