Sprawdzanie, czy zmienna DateTime ma przypisaną wartość

132

Czy istnieje łatwy sposób w C #, aby sprawdzić, czy wystąpieniu DateTime została przypisana wartość, czy nie?

Muczeć
źródło

Odpowiedzi:

83

Jedynym sposobem na posiadanie zmiennej, której nie przypisano wartości w C #, jest to, że jest ona zmienną lokalną - w takim przypadku w czasie kompilacji można stwierdzić, że nie jest ona ostatecznie przypisana, próbując odczytać z niej: )

Podejrzewam, że naprawdę chcesz Nullable<DateTime>(lub DateTime?z cukrem syntaktycznym C #) - nullzacznij od, a następnie przypisz normalną DateTimewartość (która zostanie odpowiednio przekonwertowana). Następnie możesz po prostu porównać z null(lub użyć HasValuewłaściwości), aby sprawdzić, czy została ustawiona „rzeczywista” wartość.

Jon Skeet
źródło
co powiesz na sprawdzenie, czy wartość jest równa domyślnej wartości daty i godziny. Czy takie podejście ma jakieś niezauważalne wady? if (request.StartDateTime == default (DateTime) {request.StartDateTime = DateTime.Now;}
Menol
8
@Menol: Cóż, to nie mówi o różnicy między polem, któremu celowo przypisano wartość, a polem, któremu właśnie nadano taką wartość default(DateTime). Zasadniczo traktuje jedną wartość w domenie jako „specjalną i niedostępną do normalnego użytku”, czego nie lubię.
Jon Skeet
301

czy masz na myśli tak:

DateTime datetime = new DateTime();

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

lub możesz użyć Nullable

DateTime? datetime = null;

 if (!datetime.HasValue)
 {
     //unassigned
 }
Hath
źródło
5
Tylko drugi z nich jest kuloodporny. Pierwsza zakłada coś o nieustawionej reprezentacji DateTime, co nie jest gwarantowane przez platformę. Osobiście uważam, że powinni dodać nieustawiony statyczny element członkowski dla tego scenariusza.
Rupert Rawnsley
18
Aby dodać to, co powiedział @RupertRawnsley, powinieneś faktycznie porównać z wartością domyślną (DateTime), która jest wartością nieprzypisanego DateTime. Tak się składa, że ​​jest równy MinValue, ale może się zmienić.
Tsahi Asher
32

umieść to gdzieś:

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

następnie:

DateTime datetime = ...;

if (datetime.IsEmpty())
{
    //unassigned
}
sonatique
źródło
Podoba mi się ten pomysł, ale zauważ, że w mało prawdopodobnym przypadku, gdy zmiennej DateTime została przypisana wartość, która jest wartością domyślną, ta metoda rozszerzenia zwróci nieprawidłowy wynik. Jedynym sposobem uniknięcia tego jest użycie DateTime dopuszczającej wartość null, która została już zasugerowana. Jednak nadal bardzo podoba mi się Twoja odpowiedź (i teraz ją używam), dzięki!
Klicker
@Klicker: Dziękuję za miły komentarz, ale nie jestem pewien, czy rozumiem twoją uwagę. O ile wiem, == w tym przypadku zawsze zwróci wartość true, gdy data / godzina jest równa wartości domyślnej (DateTime), niezależnie od tego, w jaki sposób data i godzina są przypisywane jako wartość domyślna. Pozwól, że wyjaśnię: właściwie drugi fragment mojej odpowiedzi jest błędny, nie będzie się kompilował, ponieważ jeśli weźmiesz pod uwagę, że jest to treść funkcji, to data i godzina nie jest przypisana, a kompilator odmówi jej użycia. Będziesz więc musiał przypisać mu wartość. Może to być wartość domyślna (DateTime) bezpośrednio lub pośrednio. Zmodyfikuję odpowiedź.
sonatique
a jeśli w innym kontekście data i godzina jest członkiem klasy i pozostaje bez zmian, środowisko wykonawcze przypisze do niej wartość domyślną (DateTime). == dla struktur faktycznie porównuje zawartość struktury, niezależnie od sposobu, w jaki struktura ostatecznie wypełniła się tą zawartością.
sonatique
Mój punkt odnosi się tak naprawdę tylko do członków klasy i mam na myśli; jeśli masz pole DateTime poziomie klasy lub mienia, które zostały przypisane do MINVALUE Twoja IsEmptymetoda zwróci true, co prawdopodobnie nie jest to, co chcesz (bo to nie jest pusty - to przypisano wartość domyślna). Myślę, że nazwa twojej metody byłaby bardziej odpowiednia jako IsDefaultValue. Ponieważ tak naprawdę nie można mieć DateTime, która nie dopuszcza wartości null IsEmpty.
Klicker
@Klicker: ah tak, OK, rozumiem. Masz rację: nazwa, którą wybrałem, wprowadza w błąd. IsDefaultValuebyłoby lepiej
sonatique
5

DateTime jest typem wartości, więc nie może nigdy mieć wartości null. Jeśli myślisz, że DateTime? (Nullable), którego możesz użyć:

DateTime? something = GetDateTime();
bool isNull = (something == null);
bool isNull2 = !something.HasValue;
TcKs
źródło
5

Właśnie się dowiedziałem, że GetHashCode () dla nieprzypisanej daty i godziny jest zawsze równe zero. Nie jestem pewien, czy jest to dobry sposób na sprawdzenie zerowej daty i godziny, ponieważ nie mogę znaleźć żadnej dokumentacji wyjaśniającej, dlaczego takie zachowanie jest wyświetlane.

if(dt.GetHashCode()==0)
{
    Console.WriteLine("DateTime is unassigned"); 
} 
Arcturus
źródło
1
GetHashCodeZwraca 0, ponieważ kleszczy (wewnętrznej reprezentacji DateTime) są również równe 0. kod skrótu obliczonego przez następujący sposób: unchecked((int)ticks) ^ (int)(ticks >> 32);. Zobacz także tutaj: referenceource.microsoft.com/#mscorlib/system/datetime.cs,836
Ivan Kochurkin
Dziękuję Ci bardzo. Próbuję serializować plik XML z klasy C # i wykluczyć atrybuty null. To pomogło.
Jim Neff
5

Użyj, Nullable<DateTime>jeśli to możliwe.

baretta
źródło
3

Powiedziałbym, że wartością domyślną jest zawsze new DateTime(). Więc możemy pisać

DateTime datetime;

if (datetime == new DateTime())
{
    //unassigned
}
Sabine
źródło
2
To rozwiązanie zostało już podane przez + Hatha w 2008 roku i, jak dodał w komentarzu + Rupert Rawnsley, nie jest kuloodporne ...
Roland Bär
0

Generalnie wolę, jeśli to możliwe, używać domyślnych wartości typów wartości w celu określenia, czy zostały one ustawione. Oczywiście nie jest to możliwe przez cały czas, szczególnie w przypadku ints - ale w przypadku DateTimes myślę, że zarezerwowanie wartości MinValue w celu wskazania, że ​​nie została zmieniona, jest wystarczająco sprawiedliwe. Zaletą tego w porównaniu z wartościami null jest to, że jest jedno miejsce mniej, w którym otrzymasz zerowy wyjątek odwołania (i prawdopodobnie wiele miejsc, w których nie musisz sprawdzać wartości null przed uzyskaniem do niego dostępu!)

Steve Dunn
źródło
0

Jeśli nie chcesz martwić się o problemy z wartością Null, takie jak sprawdzanie wartości null za każdym razem, gdy go używasz lub zawijanie go w jakąś logikę, a także nie chcesz martwić się o problemy z przesunięciem czasu, to jest to jak rozwiązałem problem:

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

Po prostu sprawdzam, czy domyślna wartość jest mniejsza niż dzień po początku czasu. Działa jak marzenie.

Urasquirrel
źródło