DateTime "null" Wert


273

Ich habe viel gesucht, aber keine Lösung gefunden. Wie gehen Sie mit einer DateTime um, die einen nicht initialisierten Wert enthalten sollte (entspricht null)? Ich habe eine Klasse, für die möglicherweise ein DateTime-Eigenschaftswert festgelegt ist oder nicht. Ich dachte daran, den Eigentümer auf DateTime.MinValue zu initialisieren, was dann leicht überprüft werden konnte. Ich denke, das ist eine ziemlich häufige Frage. Wie machst du das?

Antworten:


420

Wenn Sie sie bei normalen DateTimes überhaupt nicht initialisieren, stimmen sie überein DateTime.MinValue , da es sich eher um einen als um einen Referenztyp handelt.

Sie können auch eine nullfähige DateTime wie folgt verwenden:

DateTime? MyNullableDate;

Oder die längere Form:

Nullable<DateTime> MyNullableDate;

Und schließlich gibt es eine integrierte Methode, um auf die Standardeinstellungen eines beliebigen Typs zu verweisen. Dies gibt nullfür Referenztypen zurück, für unser DateTime-Beispiel jedoch Folgendes DateTime.MinValue:

default(DateTime)

oder in neueren Versionen von C #

default

8
Es wäre sehr hilfreich, wenn Sie ein Beispiel für die Verwendung angeben. Wie ordnen Sie die DateTime in der Datenbank, die DBNull sein könnte, der nullbaren DateTime zu?
Kirk.burleson

9
Es ist auch gut zu beachten, dass, wenn Sie sie initialisieren und mit null, sie auch zugewiesen DateTime.MinValuewerden
Jeff LaFay

2
@ kirk.burleson das sieht aus wie eine separate frage.
CompuChip

Sie müssen MyNullableDate=date; es einstellen, daraus MyDate = MyNullableDate.Value;lesen und if(MyNullableDate.HasValue)prüfen, ob es null ist
satibel

Um die Antwort "endlich" ein wenig zu verdeutlichen, ist der Standardwert von Nullable <DateTime> (DateTime?) Null, da Nullable <T> einen Referenztyp erstellt.
Ryanwebjackson

88

Wenn Sie .NET 2.0 (oder höher) verwenden, können Sie den nullbaren Typ verwenden:

DateTime? dt = null;

oder

Nullable<DateTime> dt = null;

dann später:

dt = new DateTime();

Und Sie können den Wert überprüfen mit:

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

Oder Sie können es verwenden wie:

DateTime dt2 = dt ?? DateTime.MinValue;

Weitere Informationen finden Sie hier:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx


1
Sie können nullfähige Typen auch in früheren Versionen von .NET verwenden, ohne dass 3.0 erforderlich ist.
Stephenbayer

1
Es kam in .NET 2.0 richtig? Das ? Die Syntax wurde in 3.5 zu VB.NET hinzugefügt, aber ich glaube, sie ist seit 2.0 in C #.
David Mohundro

1
Nullable-Typen sind in .Net 2.0 verfügbar. C # hat die Abkürzung gehabt? Notation von 2.0. Nur VB.Net hatte die Abkürzung nicht? in 2.0, aber Sie könnten Nullable (Of DateTime)
Mendelt

Für das letzte Snippet würde ich DateTime dt2 = dt ?? DateTime.MinValue;
Joel Coehoorn

Ich würde verwenden dt.GetValueOrDefault()- es ist die effizienteste Option.
CompuChip

37

Terminzeit? MyDateTime {get; set;}

MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);

1
Dies hat mir geholfen herauszufinden, dass das Bestehen einfach nullnicht funktioniert. Es muss sein (DateTime?)null.
Inphinite Phractals

33

Der folgende Weg funktioniert auch

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

Bitte beachten Sie, dass die Eigenschaft PublishDate DateTime sein sollte.



8

Es sei darauf hingewiesen, dass eine DateTimeVariable zwar nicht sein kann null, aber dennoch nullohne Compilerfehler verglichen werden kann:

DateTime date;
...
if(date == null) // <-- will never be 'true'
  ...

6

Sie können eine nullfähige Klasse verwenden.

DateTime? date = new DateTime?();

Es ist wahrscheinlich erwähnenswert, dass dies zu einem anderen Verhalten führt als das Instanziieren eines nicht nullbaren Wertes DateTime. Wie bereits erwähnt, erhalten Sie new DateTime()effektiv, DateTime.Minwährend new DateTime?()zu null führen.
Vitoc

6

Sie können hierfür eine nullfähige DateTime verwenden.

Nullable<DateTime> myDateTime;

oder dasselbe wie folgt geschrieben:

DateTime? myDateTime;

6

Sie können DateTime auf Nullable setzen. Standardmäßig ist DateTime nicht nullwertfähig. Sie können es auf verschiedene Arten auf Null setzen. Verwenden Sie ein Fragezeichen nach dem Typ DateTime? myTime oder mit dem generischen Stil Nullable.

DateTime? nullDate = null;

oder

DateTime? nullDate;

5

Ich stelle immer die Zeit ein DateTime.MinValue. Auf diese Weise erhalte ich keine NullErrorException und kann sie mit einem Datum vergleichen, von dem ich weiß, dass es nicht festgelegt ist.


8
Das heißt, Sie können den Unterschied zwischen "Ich brauche hier wirklich eine DateTime" und "Es ist optional" nicht erkennen - Nullable <DateTime> ist eine viel bessere Lösung, IMO.
Jon Skeet

? Ich verstehe Ihren Kommentar wirklich nicht. Ja, ich weiß, wenn die DateTime so weit von der Realität entfernt ist, ist es so, als wäre sie null ...
Patrick Desjardins

2
Es ist praktisch, aber ich betrachte DateTime.MinValue als Wert, nicht als Sonderfallbedingung. Dies kann nur zu Problemen auf der ganzen Linie führen. Ich würde mit Nullable <DateTime> gehen.
Spoulson

3
Ich denke, Sie vermissen etwas an meiner Antwort, Spoulson hat etwas geschrieben und ich habe geantwortet. Über öffentliche Mitglieder ist es nicht dasselbe und Sie wissen es. Es ist wie String.Empty oder null. Sie können beides tun, nicht weil String.Empty besser ist als null falsch. Was auch immer.
Patrick Desjardins

1
Ich bin mit Daok dabei. Es ist möglicherweise nicht der "by the book" -Ansatz, aber es ist besser, als eine NullReferenceException zu erhalten oder sich mit dem umständlichen Nullable-Typ zu befassen. Außerdem, wie viele Anwendungen gibt es tatsächlich, die sich auf das Datum 1. Januar 1 n. Chr. Verweisen müssen?
Jacobs Data Solutions

4

Seien Sie gewarnt - Wenn Sie eine Nullable verwenden, handelt es sich offensichtlich nicht mehr um ein "reines" Datum / Uhrzeit-Objekt. Daher können Sie nicht direkt auf die DateTime-Mitglieder zugreifen. Ich werde versuchen zu erklären.

Wenn Sie Nullable <> verwenden, verpacken Sie DateTime im Grunde genommen in einen Container (danke Generika), der nullbar ist - offensichtlich der Zweck. Dieser Container verfügt über eigene Eigenschaften, die Sie aufrufen können und die den Zugriff auf das oben genannte DateTime-Objekt ermöglichen. Nachdem Sie die richtige Eigenschaft verwendet haben - in diesem Fall Nullable.Value - haben Sie Zugriff auf die Standard-DateTime-Mitglieder, -Eigenschaften usw.

Nun kommt das Problem in den Sinn, wie am besten auf das DateTime-Objekt zugegriffen werden kann. Es gibt ein paar Möglichkeiten, Nummer 1 ist bei weitem die beste und 2 ist "Dude Why".

  1. Verwenden der Eigenschaft Nullable.Value

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

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

  2. Konvertieren des nullbaren Objekts in datetime mit Convert.ToDateTime (),

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

Obwohl die Antwort an dieser Stelle gut dokumentiert ist, glaube ich, dass die Verwendung von Nullable wahrscheinlich einen Beitrag wert war. Entschuldigung, wenn Sie nicht einverstanden sind.

Bearbeiten: Eine dritte Option wurde entfernt, da sie etwas zu spezifisch und fallabhängig war.


2

Obwohl Ihnen bereits jeder die Antwort gegeben hat, werde ich einen Weg erwähnen, der es einfach macht, eine Datums- / Uhrzeitangabe an eine Funktion zu übergeben

[FEHLER: System.datetime kann nicht konvertiert werden? zu system.datetime]

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

Jetzt können Sie dte ohne Probleme innerhalb der Funktion übergeben.


1

Wenn Sie manchmal Null erwarten, können Sie Folgendes verwenden:

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

Verwenden Sie in Ihrem Repository die nullfähige Datumszeit.

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

1

Ich hatte das gleiche Problem, als ich beim Durchführen eines Unit-Tests für Throws ArgumentNullException Null als Parameter für DateTime angeben musste. In meinem Fall funktionierte dies mit der folgenden Option:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));

0

Aufgrund der Art eines Datums- / Uhrzeitdatentyps kann er keinen nullWert enthalten , dh er muss einen Wert enthalten, er darf nicht leer sein oder nichts enthalten. Wenn Sie eine Datums- / Zeitvariable als markieren, nullablekönnen Sie ihr nur einen Nullwert zuweisen. Was Sie also tun möchten, ist eines von zwei Dingen (es könnte mehr geben, aber ich kann nur an zwei denken):

  • Weisen Sie Ihrer Variablen einen Mindestwert für Datum und Uhrzeit zu, wenn Sie keinen Wert dafür haben. Sie können auch einen maximalen Datums- / Zeitwert zuweisen - je nachdem, wie es Ihnen passt. Stellen Sie einfach sicher, dass Sie auf der gesamten Website konsistent sind, wenn Sie Ihre Datums- / Zeitwerte überprüfen. Entscheide dich für minoder maxund bleibe dabei.

  • Markieren Sie Ihre Datums- / Zeitvariable als nullable. Auf diese Weise können Sie Ihre Datums- / Zeitvariable auf einstellen, nullwenn Sie keine Variable haben.

Lassen Sie mich meinen ersten Punkt anhand eines Beispiels demonstrieren. Der DateTimeVariablentyp kann nicht auf null gesetzt werden, er benötigt einen Wert. In diesem Fall setze ich ihn auf denDateTime Mindestwert setzen, wenn kein Wert vorhanden ist.

Mein Szenario ist, dass ich eine BlogPostKlasse habe. Es hat viele verschiedene Felder / Eigenschaften, aber ich habe nur zwei für dieses Beispiel verwendet. DatePublishedDies ist der Zeitpunkt, an dem der Beitrag auf der Website veröffentlicht wurde und einen Datums- / Zeitwert enthalten muss. DateModifiedWenn ein Beitrag geändert wird, muss er keinen Wert enthalten, kann aber einen Wert enthalten.

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

     public DateTime DatePublished { get; set; }
}

Verwenden ADO.NET, um die Daten aus der Datenbank abzurufen (zuweisen, DateTime.MinValuedass kein Wert vorhanden ist):

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

Sie können meinen zweiten Punkt erreichen, indem Sie das DateModifiedFeld als markieren nullable. Jetzt können Sie festlegen, nullob kein Wert dafür vorhanden ist:

public DateTime? DateModified { get; set; }

Wenn ADO.NETSie die Daten aus der Datenbank abrufen, sieht sie etwas anders aus als oben (Zuweisen nullstatt DateTime.MinValue):

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

Ich hoffe, dies hilft, Verwirrung zu beseitigen. Da meine Antwort ungefähr 8 Jahre später ist, sind Sie wahrscheinlich inzwischen ein erfahrener C # -Programmierer :)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.