2012-06-08 12 views
21

Un vecchio collega di lavoro usava citare suo padre sugli strumenti: "Devi essere più intelligente di quello".Vorrei davvero restituire la data minima?

Nel seguente codice, Resharper mi sta dicendo, "Il valore assegnato non viene utilizzato in alcun percorso di esecuzione" (che punta alla prima riga). Se accetto la sua offerta di aiuto, a dt non viene assegnato un valore ("oggi").

Si tratta di un caso in cui "Devo essere più intelligente di esso" e ignorare il loro avviso, o si tratta di un caso in cui lo strumento è più intelligente di me e io non lo capisco?

La mia opinione sulla situazione è che se l'istruzione if fallisce, viene restituita la data corrente (il valore predefinito che desidero), ma se accetto le "richieste" di Resharper restituirà il valore predefinito per Datetime, che è la data minima, che presumo è qualcosa come 7/4/1776 o 1/1/0000 o giù di lì.

DateTime dt = DateTime.Now; 
if (!(DateTime.TryParse(substr, out dt))) { 
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) { 
     if (dtpDlgForm.ShowDialog() == DialogResult.OK) { 
      dt = dtpDlgForm.ReturnVal; 
     } 
    } 
} 
return dt; 
+8

Questo è un caso in cui vorrei suggerire di utilizzare più ritorni. È più ovvio se si sostituisce l'ultima riga con 'return DateTime.Now' e la riga nel mezzo dell'uso con' return dtpDlgForm.ReturnVal'. –

risposta

23

tuo destinato logica permette di tre possibili valori di ritorno delle DateTime (in ordine di preferenza):

  1. Il valore analizzato di substr.
  2. Il valore selezionato dalla finestra di dialogo.
  3. La data e l'ora correnti.

È possibile implementare questa logica avendo separati return dichiarazioni che vengono eseguiti quando la loro condizione riesce:

DateTime dt; 
if (DateTime.TryParse(substr, out dt)) 
    return dt; 

using (var dtpDlgForm = new ReturnDate(
    "Please select the Date that the file was created:")) 
{ 
    if (dtpDlgForm.ShowDialog() == DialogResult.OK) 
     return dtpDlgForm.ReturnVal; 
} 

return DateTime.Now; 

Edit: Per una spiegazione sul perché non si dovrebbe assegnare un valore a una variabile che sarà utilizzato come parametro out, fare riferimento a Mark Byers’s answer.

+2

Grazie, tutte le risposte sono state eccezionali. L'ho contrassegnato come "il" corretto, perché anche se la data non viene rilevata dal nome del file, e l'utente chiude quindi il modulo "dialog" chiedendolo per la data con un risultato della finestra di dialogo diverso da "OK" restituisce "oggi" anziché 12/7/1941 o ogni volta –

+0

Piccolo punto niggling: la linea tryParse ha bisogno di un altro virgola destra al posto del punto e virgola. –

+0

@ClayShannon: come Mike Bantegui [menzionato sopra] (http://stackoverflow.com/questions/10952470/would-i-really-want-to-return-the-minimum-date/10952537 # comment14295586_10952470), questo è un caso in cui più istruzioni 'return' possono essere preferibili dal momento che semplificano il flusso del metodo - si può semplicemente presumere che l'esecuzione del metodo si interromperà non appena si verificherà una condizione di' DateTime'. sottolineando l'errore 'TryParse', ora f ixed. – Douglas

53

La risposta è stata accettata mostra ciò che si dovrebbe essere facendo, ma non spiega il motivo per cui ReSharper lamenta, in primo luogo. Dal momento che questa spiegazione potrebbe essere utile per gli altri che trovano la tua domanda, qui è:

È dovrebbe seguire il consiglio di ReSharper e cambiare la prima linea a:

DateTime dt; 

Questo dichiara la variabile dt, ma non lo fa assegnare qualsiasi valore ad esso. Non è necessario assegnare un valore qui perché sarà definitivamente assegnato sulla riga successiva a causa dello out keyword. Dalla documentazione:

Anche se le variabili passate come out argomenti non devono essere inizializzati prima di essere passati, il metodo chiamato è necessario per assegnare un valore prima che il metodo restituisce.

Enfasi mia. Assegnare il valore DateTime.Now non è necessario e fuorviante perché questo valore non verrà mai utilizzato.

mio prendere sulla situazione è che se l'istruzione if non riesce, la data corrente viene restituito

Questo non è ciò che il codice fa. Dal documentation:

risultato: Quando questo metodo contiene il valore DateTime equivalente alla data e l'ora contenuta in s, se la conversione è riuscita, o MinValue se la conversione non è riuscita.

Con il codice che avete inviato se il parsing fallisce allora dt conterrà il valore DateTime.MinValue e non il valore DateTime.Now che si è assegnato.

+0

+1 Ottima spiegazione. In questo tipo di situazione sarei grato di avere ReSharper dalla mia parte! Ho bisogno di passare attraverso tutti i miei usi TryParse ora .... :( – surfen

20

È perché si assegna un valore a dt e quindi lo si trasmette come out param.Se una variabile viene passata come param out:

  • Deve essere assegnato un valore all'interno di una funzione prima di essere utilizzati all'interno di esso
  • Deve essere assegnato un valore prima che restituisce

nel tuo caso, è possibile correggere il messaggio dal messaggio ReSharper cambiando la prima linea a:

DateTime dt; 

mio prendere sul situazione è che se l'istruzione if fallisce, viene restituita la data corrente

Questo non è vero. Sarà sempre tornare DateTime.MinValue, indipendentemente dal valore dell'oggetto DateTime si passa

Da MSDN - DateTime.TryParse(string, out DateTime):.

risultato

Tipo: System.DateTime%

Quando questo metodo restituisce, [risultato] contiene il valore DateTime equivalente alla data e all'ora contenute in s, se la conversione riuscito, oppure MinValue se la conversione non è riuscita. La conversione non riesce se il parametro s è nullo, è una stringa vuota ("") oppure non contiene una rappresentazione stringa valida di una data e un'ora. Questo parametro è passato non inizializzato.

(enfasi aggiunta)

8

Un parametro out ha sempre un valore assegnato ad esso. È sempre garantito che la funzione chiamata assegni un valore ad esso prima di tornare. Pertanto sovrascriverà il valore inizialmente assegnato in ogni caso.

7

Il punto è sull'utilizzo out parameter modifier:

Sebbene le variabili passate come su argomenti non devono essere inizializzate prima di essere passato, il metodo chiamato è necessaria per assegnare un valore prima che il metodo ritorna.

DateTime.TryParse assegnerà un valore predefinito a dt comunque, e se non può analizzare substr, il risultante dt avrà il valore del datetime minimo.

3
DateTime.TryParse(substr, out dt); 

può restituire false ma sarà comunque modificare dt. Cercherà di completare dt al meglio delle sue capacità, inizializzando alcuni dei valori nel miglior modo possibile. Quando si utilizza il out modificatore in C#, si indica il programma per inizializzare, e non si deve aspettare di mantenere il valore si passa.

Che cosa si potrebbe fare è

DateTime dt; 
if (!(DateTime.TryParse(substr, out dt))) { 
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) { 
     if (dtpDlgForm.ShowDialog() == DialogResult.OK) { 
      dt = dtpDlgForm.ReturnVal; 
     } 
     else { 
      dt = DateTime.Now; 
     } 
    } 
} 

return dt; 
+0

Penso che il tuo codice tornerà oggi se TryParse ha successo. Non è corretto, se TryParse ha successo, il valore analizzato dovrebbe essere restituito. – comecme

+0

Oh mio Dio, hai completamente ragione. cambiato la mia risposta per riflettere questo. –

3

Questo codice renderebbe l'avviso va via. Ma penso che la risposta di Douglas sia più facile da leggere.

DateTime dt; 
if (!(DateTime.TryParse(substr, out dt))) { 
    dt = DateTime.Now; 
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) { 
     if (dtpDlgForm.ShowDialog() == DialogResult.OK) { 
      dt = dtpDlgForm.ReturnVal; 
     } 
    } 
} 
return dt; 
Problemi correlati