Memeriksa untuk melihat apakah variabel DateTime telah memiliki nilai yang ditetapkan

131

Apakah ada cara mudah dalam C # untuk memeriksa untuk melihat apakah instance DateTime telah diberi nilai atau tidak?

Melenguh
sumber

Jawaban:

83

Satu-satunya cara untuk memiliki variabel yang belum diberi nilai dalam C # adalah untuk itu menjadi variabel lokal - dalam hal ini pada saat kompilasi Anda dapat mengatakan bahwa itu tidak ditentukan dengan mencoba membaca dari itu: )

Saya menduga Anda benar-benar ingin Nullable<DateTime>(atau DateTime?dengan gula sintaksis C #) - buatlah nulluntuk memulainya dan kemudian berikan DateTimenilai normal (yang akan dikonversi dengan tepat). Kemudian Anda bisa membandingkan dengan null(atau menggunakan HasValueproperti) untuk melihat apakah nilai "nyata" telah ditetapkan.

Jon Skeet
sumber
bagaimana dengan memeriksa apakah nilainya sama dengan nilai datetime default. Apakah ada kelemahan yang tidak terlalu mencolok dari pendekatan ini? if (request.StartDateTime == default (DateTime) {request.StartDateTime = DateTime.Now;}
Menol
8
@ Molen: Yah itu tidak memberitahu perbedaan antara bidang yang sengaja diberi nilai default(DateTime)dan yang hanya seperti itu untuk memulai. Pada dasarnya itu memperlakukan satu nilai dalam domain sebagai "khusus dan tidak tersedia untuk penggunaan normal" yang saya sukai.
Jon Skeet
298

maksud Anda seperti itu:

DateTime datetime = new DateTime();

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

atau Anda bisa menggunakan Nullable

DateTime? datetime = null;

 if (!datetime.HasValue)
 {
     //unassigned
 }
Telah
sumber
5
Hanya yang kedua ini yang tahan peluru. Yang pertama mengasumsikan sesuatu tentang representasi yang tidak disetel dari DateTime yang tidak dijamin oleh kerangka kerja. Secara pribadi saya pikir mereka harus menambahkan anggota statis yang tidak disetel untuk skenario ini.
Rupert Rawnsley
18
Untuk menambahkan apa yang dikatakan @RupertRawnsley, Anda harus benar-benar membandingkan dengan default (DateTime), yang merupakan nilai DateTime yang belum ditetapkan. Kebetulan sama dengan MinValue, tetapi bisa berubah.
Tsahi Asher
32

letakkan ini di suatu tempat:

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

kemudian:

DateTime datetime = ...;

if (datetime.IsEmpty())
{
    //unassigned
}
sonatique
sumber
Saya suka ide ini, tetapi perhatikan bahwa jika variabel DateTime agaknya diberi nilai yang merupakan nilai default, metode ekstensi ini akan mengembalikan hasil yang salah. Satu-satunya cara untuk menghindari ini adalah dengan menggunakan DateTime yang dapat dibatalkan, yang telah disarankan. Saya masih sangat suka (dan sekarang menggunakan) jawaban Anda, terima kasih!
Klicker
@Klicker: Terima kasih atas komentar Anda yang baik, tetapi saya tidak yakin saya mengerti komentar Anda. Sejauh yang saya tahu == dalam hal ini akan selalu kembali benar ketika datetime setara dengan default (DateTime) apa pun cara datetime akhirnya diberi nilai default. Biarkan saya jelaskan: sebenarnya potongan kedua dalam jawaban saya salah, itu tidak akan dikompilasi, karena, jika Anda menganggap bahwa ini adalah tubuh fungsi, maka datetime tidak ditetapkan, dan kompiler akan menolak untuk menggunakannya. Jadi, Anda harus memberinya nilai. Ini bisa menjadi default (DateTime) secara langsung atau tidak langsung. Saya akan mengubah jawaban saya.
sonatique
dan jika dalam konteks lain datetime adalah anggota kelas, dan dibiarkan apa adanya, runtime akan menetapkan default (DateTime) untuknya. The == untuk struct sebenarnya membandingkan konten struct, apa pun cara akhir-akhir struct diisi dengan konten ini.
sonatique
Maksud saya hanya benar-benar berhubungan dengan anggota kelas, dan apa yang saya maksud adalah; jika Anda memiliki bidang DateTime tingkat kelas atau properti yang telah Anda tetapkan MinValue, IsEmptymetode Anda akan mengembalikan true, yang mungkin bukan yang Anda inginkan (karena itu tidak kosong - ini telah ditetapkan nilai default). Saya kira nama metode Anda akan lebih cocok sebagai IsDefaultValue. Karena Anda tidak bisa benar-benar memiliki DateTime yang tidak dapat dibatalkan itu IsEmpty.
Klicker
@ Klicker: ah ya, oke, mengerti. Anda benar: nama yang saya pilih menyesatkan. IsDefaultValueakan lebih baik
sonatique
5

DateTime adalah tipe nilai, jadi tidak mungkin nol. Jika Anda berpikir DateTime? (Tidak dapat dibatalkan), Anda dapat menggunakan:

DateTime? something = GetDateTime();
bool isNull = (something == null);
bool isNull2 = !something.HasValue;
TcK
sumber
5

Saya baru tahu bahwa GetHashCode () untuk datetime yang belum ditetapkan selalu nol. Saya tidak yakin apakah ini cara yang baik untuk mengecek null datetime, karena, saya tidak dapat menemukan dokumentasi tentang mengapa perilaku ini ditampilkan.

if(dt.GetHashCode()==0)
{
    Console.WriteLine("DateTime is unassigned"); 
} 
Arcturus
sumber
1
GetHashCodekembali 0 karena kutu (representasi internal dari DateTime) juga sama dengan 0. kode Hash dihitung dengan cara berikut: unchecked((int)ticks) ^ (int)(ticks >> 32);. Lihat juga di sini: Referenceource.microsoft.com/#mscorlib/system/datetime.cs.836
Ivan Kochurkin
Terima kasih banyak. Saya mencoba membuat serial file XML dari kelas C # dan mengecualikan atribut nol. Ini membantu.
Jim Neff
5

Gunakan Nullable<DateTime>jika memungkinkan.

baretta
sumber
3

Saya akan mengatakan nilai default selalu new DateTime(). Jadi kita bisa menulis

DateTime datetime;

if (datetime == new DateTime())
{
    //unassigned
}
Sabine
sumber
2
Solusi ini sudah diberikan oleh + Hath pada tahun 2008 dan, ketika + Rupert Rawnsley ditambahkan sebagai komentar, tidak tahan peluru ...
Roland Bär
0

Saya biasanya lebih suka, jika memungkinkan, untuk menggunakan nilai default tipe nilai untuk menentukan apakah mereka telah ditetapkan. Ini jelas tidak mungkin sepanjang waktu, terutama dengan int - tetapi untuk DateTimes, saya pikir pemesanan MinValue untuk menandakan bahwa itu belum diubah cukup adil. Manfaat dari ini lebih dari nullables adalah bahwa ada satu tempat lebih sedikit di mana Anda akan mendapatkan pengecualian referensi nol (dan mungkin banyak tempat di mana Anda tidak perlu memeriksa nol sebelum mengaksesnya!)

Steve Dunn
sumber
0

Jika Anda tidak ingin khawatir tentang masalah nilai Null seperti memeriksa null setiap kali Anda menggunakannya atau membungkusnya dalam beberapa logika, dan Anda juga tidak ingin harus khawatir tentang masalah waktu offset, maka ini adalah bagaimana saya memecahkan masalah:

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

Saya hanya memeriksa bahwa nilai defaultnya kurang dari satu hari setelah awal waktu. Bekerja seperti pesona.

Urasquirrel
sumber