Bagaimana cara menggunakan DateTime.TryParse dengan Nullable <DateTime>?

115

Saya ingin menggunakan metode DateTime.TryParse untuk mendapatkan nilai datetime dari sebuah string menjadi Nullable. Tetapi ketika saya mencoba ini:

DateTime? d;
bool success = DateTime.TryParse("some date text", out (DateTime)d);

kompilator memberitahu saya

Argumen 'out' tidak diklasifikasikan sebagai variabel

Tidak yakin apa yang harus saya lakukan di sini. Saya juga mencoba:

out (DateTime)d.Value 

dan itu juga tidak berhasil. Ada ide?

Brian Sullivan
sumber

Jawaban:

123
DateTime? d=null;
DateTime d2;
bool success = DateTime.TryParse("some date text", out d2);
if (success) d=d2;

(Mungkin ada solusi yang lebih elegan, tetapi mengapa Anda tidak melakukan sesuatu seperti di atas saja?)

Jason Kealey
sumber
3
Anda benar, saya mencari lebih dari satu baris untuk menyelesaikannya, tetapi saya kira ini akan berhasil. Tidak suka membuat variabel temp itu, terasa berantakan. : - / Sepertinya skenario ini harus didukung dengan lebih baik.
Brian Sullivan
1
lihat saran Binary Worrier untuk memasukkannya ke dalam metode ekstensi.
David Alpert
4
Mengapa Anda mentransmisikan DateTime ke DateTime? Anda tidak perlu mundur d2 sebelum meneruskannya ke TryParse.
Aaron Powell
@Slace - Saya memperbarui jawaban untuk memasukkan saran Anda.
Drew Noakes
@Jason Kealey Saya harap ini sudah diperkenalkan di VS2012, jika tidak saya harus terus menggunakan potongan kode yang bagus ini.
Pimenta
161

Seperti yang dikatakan Jason, Anda dapat membuat variabel dengan tipe yang tepat dan meneruskannya. Anda mungkin ingin merangkumnya dalam metode Anda sendiri:

public static DateTime? TryParse(string text)
{
    DateTime date;
    if (DateTime.TryParse(text, out date))
    {
        return date;
    }
    else
    {
        return null;
    }
}

... atau jika Anda menyukai operator bersyarat:

public static DateTime? TryParse(string text)
{
    DateTime date;
    return DateTime.TryParse(text, out date) ? date : (DateTime?) null;
}

Atau di C # 7:

public static DateTime? TryParse(string text) =>
    DateTime.TryParse(text, out var date) ? date : (DateTime?) null;
Jon Skeet
sumber
5
Saya mungkin tidak boleh berdebat dengan The Skeet, tapi ... Anda harus memanggil metode Anda Parse, karena saya mengharapkan metode yang disebut TryParse mengikuti konvensi TryParse dan mengembalikan boolean. ;-)
Myster
@Myster: Baik dalam kedua kasus itu tidak mengikuti konvensi yang ada persis - mereka yang dulu hanya Parsemengharapkannya untuk kembali DateTimedan melempar pengecualian pada kegagalan, bukan? Tapi ya, Anda dapat melakukan apa pun yang Anda inginkan ... dan di Noda Time, saya telah menamai metode yang relevan Parsesebagai gantinya.
Jon Skeet
1
Kata elsekunci tidak diperlukan (dalam contoh pertama Anda) karena titik akhir ifblok tidak pernah bisa dicapai.
Jeppe Stig Nielsen
1
@JeppeStigNielsen: Ya, itu tidak perlu - tetapi mungkin lebih disukai secara gaya untuk simetri. Ini hanya preferensi pribadi (dan saya juga tidak konsisten ...)
Jon Skeet
3
@Kiquenet: menggunakan else membuatnya lebih jelas bahwa satu atau jalur lain akan diambil, dan keduanya kembali. Saya menentang kode bersarang besar-besaran, tetapi dalam hal ini itu benar-benar bukan masalah IMO.
Jon Skeet
20

Ini adalah edisi yang sedikit ringkas dari saran Jason:

DateTime? d; DateTime dt;
d = DateTime.TryParse(DateTime.Now.ToString(), out dt)? dt : (DateTime?)null;

sumber
18

Anda tidak bisa karena Nullable<DateTime>merupakan tipe yang berbeda dengan DateTime. Anda perlu menulis fungsi Anda sendiri untuk melakukannya,

public bool TryParse(string text, out Nullable<DateTime> nDate)
{
    DateTime date;
    bool isParsed = DateTime.TryParse(text, out date);
    if (isParsed)
        nDate = new Nullable<DateTime>(date);
    else
        nDate = new Nullable<DateTime>();
    return isParsed;
}

Semoga ini membantu :)

EDIT: Menghapus metode ekstensi yang (jelas) tidak teruji dengan benar, karena (seperti yang ditunjukkan oleh beberapa kesalahan) metode ekstensi yang mencoba mengubah parameter "ini" tidak akan berfungsi dengan Jenis Nilai.

PS The Bad Hoor yang dimaksud adalah teman lama :)

Biner Worrier
sumber
Ya tidak ingin masuk tanggal [karena Anda menggunakannya sebagai parameter keluar] OK, saya akan berhenti menjadi pilih-pilih!
Ruben Bartelink
Tidak memiliki kompiler pada saya, tetapi karena DateTime adalah tipe nilai, apakah metode ekstensi def mengkompilasi?
Ruben Bartelink
Hasil tidak akan kembali kecuali Anda membuatnya - [TestFixture] kelas publik WhenExtending {[Test] public void TryParseShouldWork () {DateTime? x = nol; var res = Externders.TryParse (x, "1/1/1990"); Assert.IsTrue (res)
Ruben Bartelink

; Assert.That (x! = Null); }} gagal pada Assert. Artinya, hasilnya tidak bisa dimodifikasi karena DateTime adalah tipe nilai (yang selalu merupakan pertanyaan yang bagus di layar ponsel: D)
Ruben Bartelink
(obv yang pertama (non-ekstensi) akan bekerja, tetapi harus keluar, bukan ref - dan Anda harus membatalkan hasilnya jika gagal untuk menyesuaikan dengan API TryXXX secara umum - Cukup yakin FDG menyebutkan itu. Man, am Saya pilih-pilih!
Ruben Bartelink
4

Bagaimana dengan membuat metode ekstensi?

public static class NullableExtensions
{
    public static bool TryParse(this DateTime? dateTime, string dateString, out DateTime? result)
    {
        DateTime tempDate;
        if(! DateTime.TryParse(dateString,out tempDate))
        {
            result = null;
            return false;
        }

        result = tempDate;
        return true;

    }
}
pengguna2687864
sumber
2
Untuk apa parameter pertama itu dateTime? Itu tidak pernah digunakan.
Mike Zboray
1
@mikez - begitulah cara kerja metode ekstensi, ini digunakan oleh kompilator untuk mengetahui bahwa itu harus menjadi metode ekstensi.
Erik Funkenbusch
3
@MystereMan Saya tahu apa itu metode ekstensi. Tanda tangan yang lebih tepat untuk metode ekstensi adalah DateTime? TryParse(this string dateString). Penerapan ini sungguh aneh.
Mike Zboray
3
@ mikez - lalu mengapa Anda bertanya untuk apa? Mengapa mencemari namespace string saat Anda hanya membutuhkannya untuk waktu waktu? Tujuannya adalah untuk memberikan analog ke DateTime.TryParse yaitu DateTime? .TryParse
Erik Funkenbusch
1
@ErikFunkenbusch Metode ekstensi ini tidak akan mengizinkan sintaks panggilan seperti (DateTime?).TryParse( ... )atau Nullable<DateTime>.TryParse( ... ). Jadi mike z benar, ini adalah tanda tangan konyol untuk metode ini.
Jeppe Stig Nielsen
1

Saya tidak mengerti mengapa Microsoft tidak menangani ini. Sebuah metode utilitas kecil yang cerdas untuk menangani ini (saya punya masalah dengan int, tetapi mengganti int dengan DateTime akan memiliki efek yang sama, bisa jadi .....

    public static bool NullableValueTryParse(string text, out int? nInt)
    {
        int value;
        if (int.TryParse(text, out value))
        {
            nInt = value;
            return true;
        }
        else
        {
            nInt = null;
            return false;
        }
    }
JStrahl
sumber
1

Ini adalah satu-satunya liner yang Anda cari:

DateTime? d = DateTime.TryParse("some date text", out DateTime dt) ? dt : null;

Jika Anda ingin menjadikannya metode ekstensi semu TryParse yang tepat, Anda dapat melakukan ini:

public static bool TryParse(string text, out DateTime? dt)
{
    if (DateTime.TryParse(text, out DateTime date))
    {
        dt = date;
        return true;
    }
    else
    {
        dt = null;
        return false;
    }
}
cpcolella
sumber
@robnick Apa bedanya dengan yang saya katakan?
cpcolella
1
Abaikan komentar saya sebelumnya (saya telah memberi suara positif solusi Anda!), Untuk C # terbaru saya perlu membuang null: DateTime? d = DateTime.TryParse (bla, keluar DateTime dt)? dt: (DateTime?) null;
robnick
1

Berikut solusi satu baris:

DateTime? d = DateTime.TryParse("text", out DateTime parseDate) ? parseDate : (DateTime?)null;
pengguna1267054
sumber
-3

Alternatifnya, jika Anda tidak khawatir dengan kemungkinan pengecualian yang dimunculkan, Anda dapat mengubah TryParse untuk Parse:

DateTime? d = DateTime.Parse("some valid text");

Meskipun tidak akan ada boolean yang menunjukkan keberhasilan, ini bisa menjadi praktis dalam beberapa situasi di mana Anda tahu bahwa teks masukan akan selalu valid.

monsieurgutix
sumber