Come si utilizza DateTime.TryParse con un <DateTime> nullable?


115

Voglio usare il metodo DateTime.TryParse per ottenere il valore datetime di una stringa in un valore nullable. Ma quando provo questo:

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

il compilatore mi dice

L'argomento "out" non è classificato come variabile

Non sono sicuro di cosa devo fare qui. Ho anche provato:

out (DateTime)d.Value 

e neanche questo funziona. Qualche idea?

Risposte:


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

(Potrebbero esserci soluzioni più eleganti, ma perché non fai semplicemente qualcosa come sopra?)


3
Hai ragione, stavo cercando più di una battuta per farlo, ma suppongo che andrà bene. Non mi piace creare quella variabile temp, sembra disordinato. : - / Sembra che questo scenario dovrebbe essere supportato meglio.
Brian Sullivan

1
vedere il suggerimento di Binary Worrier di psuedo-inline che in un metodo di estensione.
David Alpert

4
Perché stai trasmettendo un DateTime a un DateTime? Non è necessario riclassificare d2 prima di passarlo a TryParse.
Aaron Powell

@Slace - Ho aggiornato la risposta per incorporare il tuo suggerimento.
Drew Noakes

@ Jason Kealey Spero che questo sia già introdotto in VS2012, altrimenti dovrò continuare a usare questo buon pezzo di codice.
Pimenta

161

Come dice Jason, puoi creare una variabile del tipo giusto e passarla. Potresti volerlo incapsulare nel tuo metodo:

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

... o se ti piace l'operatore condizionale:

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

O in C # 7:

public static DateTime? TryParse(string text) =>
    DateTime.TryParse(text, out var date) ? date : (DateTime?) null;

5
Probabilmente non dovrei discutere con The Skeet, ma ... dovresti chiamare il tuo metodo Parse, poiché mi aspetterei che un metodo chiamato TryParse segua la convenzione TryParse e restituisca un valore booleano. ;-)
Myster

@ Myster: Beh, in nessuno dei due casi segue l'esatta convenzione esistente - quelli abituati Parsesi aspettavano che tornasse DateTimee lanciasse un'eccezione in caso di fallimento, giusto? Ma sì, puoi fare quello che vuoi ... e in Noda Time, ho invece nominato i metodi pertinenti Parse.
Jon Skeet

1
La elseparola chiave non è necessaria (nel tuo primo esempio) poiché il punto finale del ifblocco non può mai essere raggiunto.
Jeppe Stig Nielsen

1
@JeppeStigNielsen: Sì, non è necessario, ma potrebbe essere stilisticamente preferibile per la simmetria. È solo una preferenza personale (e nemmeno io sono coerente ...)
Jon Skeet

3
@Kiquenet: usando else rende più chiaro che l'uno o l'altro percorso verrà preso ed entrambi torneranno. Sono contrario al codice nidificato in modo massiccio, ma in questo caso non è davvero un problema IMO.
Jon Skeet

20

Ecco un'edizione leggermente concisa di ciò che Jason ha suggerito:

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

18

Non puoi perché Nullable<DateTime>è un tipo diverso da DateTime. Devi scrivere la tua funzione per farlo,

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;
}

Spero che questo ti aiuti :)

EDIT: Rimosso il metodo di estensione (ovviamente) testato in modo improprio, perché (come sottolineato da alcuni errori) i metodi di estensione che tentano di modificare il parametro "this" non funzioneranno con i tipi di valore.

PS Il Bad Hoor in questione è un vecchio amico :)


Non vuoi iniziare l'appuntamento [visto che lo usi come parametro di uscita] OK, smetterò di essere pignolo!
Ruben Bartelink,

Non ho compilatore su di me, ma poiché DateTime è un tipo di valore, il metodo di estensione def viene compilato?
Ruben Bartelink,

Il risultato non torna a meno che tu non riesca a farlo - [TestFixture] public class WhenExtending {[Test] public void TryParseShouldWork () {DateTime? x = null; var res = Externders.TryParse (x, "1/1/1990"); Assert.IsTrue (res)
Ruben Bartelink

; Assert.That (x! = Null); }} fallisce sull'asserzione, ovvero il risultato non viene modificato poiché DateTime è un tipo di valore (che è sempre una bella domanda da eliminare sugli schermi dei telefoni: D)
Ruben Bartelink

(ovviamente il primo (senza estensione) funzionerà, ma dovrebbe essere fuori, non ref - e dovresti annullare il risultato se non si adatta alle API TryXXX in generale - Sono abbastanza sicuro che FDG lo menziona. Sono
pignolo

4

Che ne dici di creare un metodo di estensione?

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;

    }
}

2
A cosa serve il primo parametro dateTime? Non viene mai utilizzato.
Mike Zboray

1
@mikez: è così che funzionano i metodi di estensione, viene utilizzato dal compilatore per sapere che dovrebbe essere un metodo di estensione.
Erik Funkenbusch

3
@ MystereMan So cos'è un metodo di estensione. Una firma più appropriata per un metodo di estensione sarebbe DateTime? TryParse(this string dateString). Questa implementazione è semplicemente bizzarra.
Mike Zboray

3
@mikez - allora perché hai chiesto a cosa serviva? Perché inquinare lo spazio dei nomi della stringa quando ne hai bisogno solo per datetime? Lo scopo è fornire un analogo a DateTime.TryParse che è DateTime?. TryParse
Erik

1
@ErikFunkenbusch Questo metodo di estensione non consentirà una sintassi di chiamata come (DateTime?).TryParse( ... )o Nullable<DateTime>.TryParse( ... ). Quindi Mike Z ha ragione, questa è una stupida firma per il metodo.
Jeppe Stig Nielsen

1

Non vedo perché Microsoft non abbia gestito questo. Un piccolo metodo di utilità intelligente per affrontare questo (ho avuto il problema con int, ma sostituire int con DateTime sarà lo stesso effetto, potrebbe essere .....

    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;
        }
    }

1

Questa è l'unica linea che stai cercando:

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

Se vuoi renderlo un metodo di pseudo estensione TryParse appropriato, puoi farlo:

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;
    }
}

@robnick In che modo è diverso da quello che ho detto?
cpcolella

1
Ignora il mio commento precedente (ho votato la tua soluzione!), Per l'ultimo C # avevo bisogno di eseguire il cast del null: DateTime? d = DateTime.TryParse (blah, out DateTime dt)? dt: (DateTime?) null;
robnick

1

Ecco una soluzione a linea singola:

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

-3

In alternativa, se non sei preoccupato per la possibile eccezione sollevata, puoi cambiare TryParse per Parse:

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

Anche se non ci sarà nemmeno un valore booleano che indichi il successo, potrebbe essere pratico in alcune situazioni in cui sai che il testo di input sarà sempre valido.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.