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?

Matten
quelle

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
Joel Coehoorn
quelle
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

Mark Ingram
quelle
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"]);
Iman
quelle
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.

Aleksei
quelle
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'
  ...
Uncoder
quelle
6

Sie können eine nullfähige Klasse verwenden.

DateTime? date = new DateTime?();
Aaron Smith
quelle
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;
Patrik Svensson
quelle
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;
user29958
quelle
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.

Patrick Desjardins
quelle
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.

Gabe
quelle
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.

Keine Feiertage
quelle
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){...}
DarkoM
quelle
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));
Kiril Dobrev
quelle
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 :)

Brendan Vogt
quelle