DateTime "null" valeur

273

J'ai beaucoup cherché mais je n'ai pas trouvé de solution. Comment gérez-vous un DateTime qui devrait pouvoir contenir une valeur non initialisée (équivalente à null)? J'ai une classe qui pourrait avoir une valeur de propriété DateTime définie ou non. Je pensais à initialiser le propriétaire de la propriété à DateTime.MinValue, qui pourrait ensuite être facilement vérifié. Je suppose que c'est une question assez courante, comment faites-vous cela?

Des nattes
la source

Réponses:

420

Pour les DateTimes normaux, si vous ne les initialisez pas du tout, ils correspondront DateTime.MinValue, car il s'agit d'un type de valeur plutôt que d'un type de référence.

Vous pouvez également utiliser un DateTime nullable, comme ceci:

DateTime? MyNullableDate;

Ou la forme plus longue:

Nullable<DateTime> MyNullableDate;

Et, enfin, il existe une méthode intégrée pour référencer la valeur par défaut de tout type. Cela renvoie nullpour les types de référence, mais pour notre exemple DateTime, il retournera la même chose que DateTime.MinValue:

default(DateTime)

ou, dans les versions plus récentes de C #,

default
Joel Coehoorn
la source
8
Il serait très utile de fournir un exemple d'utilisation. Comment attribuez-vous le DateTime dans la base de données, qui pourrait être DBNull, au DateTime nullable?
kirk.burleson
9
Il est également bon de noter que lorsque vous les initialisez et nuls, ils sont attribués DateTime.MinValueaussi bien
Jeff Lafay
2
@ kirk.burleson qui ressemble à une question distincte.
CompuChip
vous devrez le MyNullableDate=date; définir, MyDate = MyNullableDate.Value;le lire et if(MyNullableDate.HasValue)vérifier s'il est nul
satibel
Pour clarifier un peu "enfin" la réponse - la valeur par défaut de Nullable <DateTime> (DateTime?) Est nulle, car Nullable <T> crée un type de référence.
ryanwebjackson
88

Si vous utilisez .NET 2.0 (ou version ultérieure), vous pouvez utiliser le type nullable:

DateTime? dt = null;

ou

Nullable<DateTime> dt = null;

puis plus tard:

dt = new DateTime();

Et vous pouvez vérifier la valeur avec:

if (dt.HasValue)
{
  // Do something with dt.Value
}

Ou vous pouvez l'utiliser comme:

DateTime dt2 = dt ?? DateTime.MinValue;

Vous pouvez en savoir plus ici:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

Mark Ingram
la source
1
Vous pouvez utiliser des types nullables même dans les versions antérieures de .NET, pas besoin de 3.0.
stephenbayer
1
Il est venu dans .NET 2.0 à droite? Le ? la syntaxe a été ajoutée à VB.NET en 3.5, mais elle est en C # depuis 2.0 je crois.
David Mohundro
1
Les types nullables sont disponibles dans .Net 2.0. C # a eu la sténographie? notation à partir de 2.0. Seul VB.Net n'avait pas la sténographie? en 2.0 mais vous pouvez utiliser Nullable (Of DateTime)
Mendelt
Pour le dernier extrait, je dirais DateTime dt2 = dt ?? DateTime.MinValue;
Joel Coehoorn
J'utiliserais dt.GetValueOrDefault()- c'est l'option la plus efficace.
CompuChip
37

DateTime? MyDateTime {get; set;}

MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);
Iman
la source
1
Cela m'a aidé à découvrir que le passage nullne fonctionne tout simplement pas. Cela doit être (DateTime?)null.
Inphinite Phractals
33

La voie suivante fonctionne également

myClass.PublishDate = toPublish ? DateTime.Now : (DateTime?)null;

Veuillez noter que la propriété PublishDate doit être DateTime?

Aleksei
la source
12

J'envisagerais d'utiliser un type nullable .

DateTime? myDateau lieu de DateTime myDate.

David Mohundro
la source
8

Il convient de souligner que, même si une DateTimevariable ne peut pas l'être null, elle peut toujours être comparée nullsans erreur de compilation:

DateTime date;
...
if(date == null) // <-- will never be 'true'
  ...
décodeur
la source
6

Vous pouvez utiliser une classe nullable.

DateTime? date = new DateTime?();
Aaron Smith
la source
Il est probablement intéressant de noter que cela vous donnera un comportement différent de l'instanciation d'un non-nullable DateTime. Comme mentionné précédemment, new DateTime()vous donnera effectivement DateTime.Minalors que new DateTime?()résultera en null.
Vitoc
6

Vous pouvez utiliser un DateTime nullable pour cela.

Nullable<DateTime> myDateTime;

ou la même chose écrite comme ceci:

DateTime? myDateTime;
Patrik Svensson
la source
6

Vous pouvez définir le DateTime sur Nullable. Par défaut, DateTime n'est pas nullable. Vous pouvez le rendre nullable de deux manières. Vous utilisez un point d'interrogation après le type DateTime? myTime ou en utilisant le style générique Nullable.

DateTime? nullDate = null;

ou

DateTime? nullDate;
user29958
la source
5

Je fixe toujours l'heure DateTime.MinValue. De cette façon, je n'obtiens aucune NullErrorException et je peux le comparer à une date dont je sais qu'elle n'est pas définie.

Patrick Desjardins
la source
8
Cela signifie que vous ne pouvez pas faire la différence entre "J'ai vraiment besoin d'un DateTime ici" et "C'est facultatif" - Nullable <DateTime> est une bien meilleure solution, IMO.
Jon Skeet
? Je ne comprends vraiment pas votre commentaire. Ouais je sais quand le DateTime est si loin que la réalité est comme s'il était nul ...
Patrick Desjardins
2
C'est pratique, mais je considère DateTime.MinValue comme une valeur, pas comme une condition spéciale. Cela ne peut que conduire à des problèmes sur toute la ligne. J'irais avec Nullable <DateTime>.
spoulson
3
Je pense que vous manquez quelque chose dans ma réponse, Spoulson a écrit quelque chose et je répondais. À propos des membres du public, eh bien ce n'est pas pareil et vous le savez. c'est comme String.Empty ou null. Vous pouvez faire les deux, pas parce que String.Empty vaut mieux que null est faux. Peu importe.
Patrick Desjardins
1
Je suis avec Daok là-dessus. Ce n'est peut-être pas l'approche «à la livre», mais c'est mieux que d'obtenir une exception NullReferenceException ou de traiter le type Nullable encombrant. De plus, combien d'applications existe-t-il qui doivent réellement faire référence à la date du 1er janvier 1 AD?
Jacobs Data Solutions
4

Soyez juste averti - Lorsque vous utilisez un Nullable, ce n'est évidemment plus un objet datetime «pur», en tant que tel, vous ne pouvez pas accéder directement aux membres DateTime. Je vais essayer d'expliquer.

En utilisant Nullable <>, vous enveloppez essentiellement DateTime dans un conteneur (merci génériques) dont la valeur est nullable - évidemment son objectif. Ce conteneur possède ses propres propriétés que vous pouvez appeler pour donner accès à l'objet DateTime susmentionné; après avoir utilisé la bonne propriété - dans ce cas Nullable.Value - vous avez alors accès aux membres, propriétés, etc. de DateTime standard.

Donc - maintenant, le problème vient à l'esprit quant à la meilleure façon d'accéder à l'objet DateTime. Il y a plusieurs façons, le numéro 1 est de loin le meilleur et 2 est "mec pourquoi".

  1. En utilisant la propriété Nullable.Value,

    DateTime date = myNullableObject.Value.ToUniversalTime(); //Works

    DateTime date = myNullableObject.ToUniversalTime(); //Not a datetime object, fails

  2. Conversion de l'objet nullable en datetime à l'aide de Convert.ToDateTime (),

    DateTime date = Convert.ToDateTime(myNullableObject).ToUniversalTime(); //works but why...

Bien que la réponse soit bien documentée à ce stade, je pense que l'utilisation de Nullable valait probablement la peine d'être publiée. Désolé si vous n'êtes pas d'accord.

edit: Suppression d'une troisième option car elle était un peu trop spécifique et dépendait de la casse.

Gabe
la source
2

Bien que tout le monde vous ait déjà donné la réponse, je mentionnerai un moyen qui permet de passer facilement un datetime dans une fonction

[ERREUR: impossible de convertir system.datetime? à system.datetime]

DateTime? dt = null;
DateTime dte = Convert.ToDateTime(dt);

Vous pouvez maintenant passer dte à l'intérieur de la fonction sans aucun problème.

Pas de vacances
la source
1

Si vous vous attendez parfois à null, vous pouvez utiliser quelque chose comme ceci:

var orderResults = Repository.GetOrders(id, (DateTime?)model.DateFrom, (DateTime?)model.DateTo)

Dans votre référentiel, utilisez datetime nullable.

public Orders[] GetOrders(string id, DateTime? dateFrom, DateTime? dateTo){...}
DarkoM
la source
1

J'ai eu le même problème que je devais donner Null comme paramètre pour DateTime lors de l'exécution du test unitaire pour Throws ArgumentNullException.Il a fonctionné dans mon cas en utilisant l'option suivante:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));
Kiril Dobrev
la source
0

Étant donné la nature d'un type de données date / heure, il ne peut pas contenir de nullvaleur, c'est-à-dire qu'il doit contenir une valeur, il ne peut pas être vide ou ne rien contenir. Si vous marquez une variable date / heure comme nullablealors, vous pouvez lui attribuer une valeur nulle. Donc, ce que vous cherchez à faire est l'une des deux choses (il y en a peut-être plus mais je ne pense qu'à deux):

  • Attribuez une valeur de date / heure minimale à votre variable si vous n'en avez pas de valeur. Vous pouvez également attribuer une valeur de date / heure maximale, selon la manière qui vous convient. Assurez-vous simplement que vous êtes cohérent à l'échelle du site lorsque vous vérifiez vos valeurs de date / heure. Décidez d'utiliser minou maxet respectez-le.

  • Marquez votre variable date / heure comme nullable. De cette façon, vous pouvez définir votre variable date / heure nullsi vous ne disposez pas d'une variable.

Permettez-moi de démontrer mon premier point en utilisant un exemple. Le DateTimetype de variable ne peut pas être défini sur null, il a besoin d'une valeur, dans ce cas, je vais le définir à la DateTimevaleur minimale de s'il n'y a pas de valeur.

Mon scénario est que j'ai une BlogPostclasse. Il a de nombreux champs / propriétés différents mais j'ai choisi de n'en utiliser que deux pour cet exemple. DatePublishedcorrespond au moment où la publication a été publiée sur le site Web et doit contenir une valeur date / heure. DateModifiedc'est quand un article est modifié, il ne doit donc pas contenir de valeur, mais peut contenir une valeur.

public class BlogPost : Entity
{
     public DateTime DateModified { get; set; }

     public DateTime DatePublished { get; set; }
}

Utilisation ADO.NETpour obtenir les données de la base de données (attribuer DateTime.MinValues'il n'y a pas de valeur):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? DateTime.MinValue : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

Vous pouvez accomplir mon deuxième point en marquant le DateModifiedchamp comme nullable. Vous pouvez maintenant le définir nulls'il n'y a pas de valeur:

public DateTime? DateModified { get; set; }

En utilisant ADO.NETpour obtenir les données de la base de données, cela ressemblera un peu à la façon dont cela a été fait ci-dessus (en assignant nullau lieu de DateTime.MinValue):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? (DateTime?)null : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

J'espère que cela aide à dissiper toute confusion. Étant donné que ma réponse est d'environ 8 ans plus tard, vous êtes probablement un programmeur C # expert maintenant :)

Brendan Vogt
la source