2008-10-21 21 views
216

Szukałem dużo, ale nie mogłem znaleźć rozwiązania. Jak radzisz sobie z DateTime, które powinno zawierać niezainicjowaną wartość (równoważną zeru)? Mam klasę, która może mieć ustawioną wartość właściwości DateTime lub nie. Zastanawiałem się nad zainicjowaniem właściciela nieruchomości na DateTime.MinValue, który następnie można łatwo sprawdzić. Sądzę, że jest to dość powszechne pytanie, jak to zrobić?DateTime "null" value

Odpowiedz

332

Dla normalnych datowań, jeśli ich nie zainicjalizujesz, będą pasować do DateTime.MinValue, ponieważ jest to typ wartości, a nie typ referencyjny.

Można również użyć zerowalne DateTime w następujący sposób:

DateTime? MyNullableDate; 

lub dłuższych postać:

Nullable<DateTime> MyNullableDate; 

I wreszcie, jest zbudowany w sposób odwoływać się do domyślnego dowolnego typu . Ten wraca null dla typów referencyjnych, ale dla naszego przykładu DateTime powróci taka sama jak DateTime.MinValue:

default(DateTime) 
+7

Byłoby znacznie pomóc, jeśli podaj przykład, jak z niego korzystać. W jaki sposób przypisać DateTime w bazie danych, która może być DBNull, do null daty DateTime? –

+6

Warto również zauważyć, że po zainicjowaniu ich z wartością null są one przypisane również do zmiennej "DateTime.MinValue" – jlafay

+1

@ kirk.burleson, która wygląda jak oddzielne pytanie. – CompuChip

71

Jeśli używasz .NET 2.0 (lub nowszy) można użyć typu zerowalne:

DateTime? dt = null; 

lub

Nullable<DateTime> dt = null; 

potem:

dt = new DateTime(); 

a ty można sprawdzić wartość za pomocą:

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

Albo można go używać jak:

DateTime dt2 = dt ?? DateTime.MinValue; 

można przeczytać więcej tutaj:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

+1

Można używać typów zerowalnych, nawet we wcześniejszych wersjach .NET, bez potrzeby 3.0. – stephenbayer

+1

Typo, zaktualizowałem to. –

+1

Przyszedł w .NET 2.0, prawda? ? Składnia została dodana do VB.NET w wersji 3.5, ale od 2.0 jest w C#. –

5

Można użyć zerowalne klasę.

DateTime? date = new DateTime?(); 
5

Można użyć do tego celu funkcji Nałożonej do edycji DateTime.

Nullable<DateTime> myDateTime; 

lub samo napisane tak:

DateTime? myDateTime; 
5

zawsze ustawić czas DateTime.MinValue. W ten sposób nie otrzymuję żadnego wyjątku NullErrorException i mogę porównać go z datą, o której wiem, że nie jest ustawiona.

+8

Oznacza to, że nie można odróżnić "naprawdę potrzebuję tu daty" i "jest opcjonalna" - Nullable jest znacznie lepszym rozwiązaniem, IMO. –

+0

? Naprawdę nie dostaję twojego komentarza. Tak, wiem, że kiedy DateTime jest tak daleko od rzeczywistości, to jest tak, jakby była zerowa ... –

+0

Po prostu sugeruję inne rozwiązanie. Zamiast powtarzać to, co zasugerowano już 10 razy. –

4

Można ustawić wartość DateTime na Nullable. Domyślnie DateTime nie jest null. Możesz go unieszkodliwić na kilka sposobów. Używanie znaku zapytania po typie DateTime? myTime lub używając ogólnego stylu Nullable. Dodałem kilka linków na msdn.

Using Nullable

Nullable

20

DateTime? MyDateTime {get; set;}

MyDateTime = (drOrder["Field1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)drOrder["Field1"]); 
1

Jeśli są, czasami, oczekując zerowy można użyć mniej więcej tak:

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

W repozytorium stosowania zerowej-stanie datetime.

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

Warto zwrócić uwagę, że choć zmienna DateTime nie może być null, to nadal można porównać do null bez błędu kompilatora:

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

Tylko ostrzegam - W przypadku korzystania z pustych jego oczywiście nie jest to już "czysty" obiekt datetime, ponieważ nie można uzyskać bezpośredniego dostępu do członków DateTime. Spróbuję to wyjaśnić.

Używając Nullable <> zasadniczo pakujesz DateTime w pojemnik (dziękuję, generics), który jest nullowany - oczywiście jego cel. Ten kontener ma swoje własne właściwości, do których możesz zadzwonić, co umożliwi dostęp do wspomnianego obiektu DateTime; po użyciu poprawnej właściwości - w tym przypadku Nullable.Value - masz wtedy dostęp do standardowych elementów DateTime, właściwości itp.

A więc - teraz przychodzi na myśl kwestia najlepszego sposobu uzyskania dostępu do obiektu DateTime. Istnieje kilka sposobów, numer 1 to FAR najlepszy a 2 to "koleś dlaczego".

  1. Wykorzystując tę ​​właściwość Nullable.Value,

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

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

  2. Konwersja zerowalne przedmiotu do datetime pomocą Convert.ToDateTime()

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

Mimo że odpowiedź jest dobrze udokumentowana w tym miejscu, uważam, że prawdopodobnie warto było opublikować informacje na temat Nullable. Przepraszam, jeśli się nie zgadzasz.

edytuj: Usunięto trzecią opcję, ponieważ była ona nieco zbyt szczegółowa i zależna od przypadku.

2

Chociaż wszyscy już wam odpowiedź, będę wspomnieć sposób, który sprawia, że ​​łatwo zdać datetime do funkcji

[Błąd: nie można przekonwertować System.DateTime? do System.DateTime]

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

Teraz można przejść DTE wewnątrz funkcji bez żadnych problemów.

-1

Biorąc pod uwagę charakter typu data/czas, nie może zawierać wartości null, tj. Musi zawierać wartość, nie może być pusta ani zawierać niczego. Jeśli oznaczysz zmienną daty/czasu jako nullable, możesz tylko przypisać do niej wartość zerową. Więc czego szukasz zrobić, to jedna z dwóch rzeczy (nie może być więcej, ale mogę myśleć tylko z dwóch):

  • Przypisywanie minimalną wartość daty/czasu do zmiennej, jeśli nie masz wartość dla niego. Możesz także przypisać maksymalną wartość daty/czasu - w zależności od tego, która metoda Ci odpowiada. Upewnij się, że podczas sprawdzania wartości daty/czasu jesteś konsekwentny w całej witrynie. Zdecyduj się na używanie min lub max i trzymaj się go.

  • Oznacz zmienną daty/czasu jako nullable. W ten sposób możesz ustawić zmienną daty/czasu na null, jeśli nie masz do niej zmiennej.

Pozwól mi zademonstrować swój pierwszy punkt za pomocą przykładu. Typ zmiennej DateTime nie może mieć wartości null, potrzebuje wartości, w tym przypadku ustawię ją na minimalną wartość DateTime, jeśli nie ma żadnej wartości.

Mój scenariusz jest taki, że mam klasę BlogPost. Ma wiele różnych pól/właściwości, ale wybrałem tylko dwa dla tego przykładu. DatePublished jest, gdy post został opublikowany na stronie i musi zawierać wartość daty/czasu. DateModified jest, gdy post jest modyfikowany, więc nie musi zawierać wartości, ale może zawierać wartość.

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

    public DateTime DatePublished { get; set; } 
} 

Korzystanie ADO.NET aby uzyskać dane z bazy danych (przypisanie DateTime.MinValue to nie ma wartości):

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

można osiągnąć mój drugi punkt zaznaczając pole DateModified jak nullable. Teraz można ustawić go null jeśli nie ma wartości dla niego:

public DateTime? DateModified { get; set; } 

Korzystanie ADO.NET aby uzyskać dane z bazy danych, to będzie wyglądać nieco inaczej na drodze to miało powyżej (przypisywanie null zamiast DateTime.MinValue):

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

mam nadzieję, że to pomaga wyjaśnić wszelkie nieporozumienia. Biorąc pod uwagę, że moja odpowiedź jest około 8 lat później prawdopodobnie jesteś ekspertem C# programista teraz :)

7

ten sposób działa również

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

Należy pamiętać, że nieruchomość powinna być PublishDate DateTime?

1

miałem ten sam problem jak miałem dać Null jako parametr DateTime podczas wykonywania testów jednostkowych dla Zgłasza ArgumentNullException.It pracował w moim przypadku stosując następującą opcję:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null)); 
Powiązane problemy