Quando si suppone che "Try" sia usato nei nomi dei metodi C #?


180

Stavamo discutendo con i nostri colleghi su cosa significhi se il nome del metodo inizia con "Prova".

C'erano le seguenti opinioni:

  • Utilizzare "Prova" quando il metodo può restituire un valore null.
  • Utilizzare "Prova" quando il metodo non genera un'eccezione.

Qual è la definizione ufficiale? Cosa dice "Prova" nel nome del metodo? C'è qualche linea guida ufficiale su questo?


83
+1 Le persone che mettono così tanto in considerazione i nomi delle loro funzioni in realtà cercano "il prossimo". Non sono sicuro del motivo per cui questo sta ottenendo voti stretti (e questo proviene da un ragazzo che ne ha lanciati molti stasera.)
Jonathon Reinhart,

7
@JonathonReinhart, ha ottenuto voti stretti perché "
Pranav Hosangadi,

16
V'è una dichiarazione ufficiale da parte di Microsoft che risponde alla domanda (vedi la mia risposta). In che modo non è un dato di fatto?
Erik Schierboom,

6
@PranavHosangadi, come menzionato da Erik, è supportato da fatti. Inoltre, ci sono molti sviluppatori C # molto esperti qui che hanno competenze specifiche per fornire una risposta valida. Diavolo, Eric Lippert è il principale architetto del linguaggio C #. Penso che tu possa chiamare quella specifica competenza .
Jonathon Reinhart,

4
@ErikSchierboom Che sia la linea guida MS è un dato di fatto. Che la linea guida MS sia la linea guida corretta da usare è soggettiva e discutibile.
Servito il

Risposte:


148

Questo è noto come modello TryParse ed è stato documentato da Microsoft. La pagina MSDN ufficiale di eccezioni e prestazioni dice :

Considerare il modello TryParse per i membri che possono generare eccezioni in scenari comuni per evitare problemi di prestazioni correlati alle eccezioni.

Pertanto, se si dispone di codice per il quale un caso d'uso normale significherebbe che potrebbe generare un'eccezione (come l'analisi di un int), il modello TryParse ha senso.


2
Un altro link utile che documenta questo modello (ricerca di TryParse) blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
Vivek Maharajh

2
Fondamentalmente, se si dispone di un metodo TryParse, è necessario disporre di un metodo Parse che genera quando TryParse restituisce false. Al contrario, se hai un metodo Parse, dovresti considerare di avere un metodo TryParse che restituisca false quando Parse
lancerebbe

5
+1. Solo per aggiungere a questo, le eccezioni sono generalmente per circostanze "eccezionali". Se stai facendo qualcosa che potrebbe facilmente fallire e che il fallimento non è particolarmente evidente, allora usare questo schema è più idiomatico di un tentativo / cattura
Adam Robinson,

Un modello del genere ha davvero richiesto le linee guida di Microsoft? Sembra roba abbastanza semplice.
Dave Lawrence,

19
Si è roba di base, ma questo non significa che le linee guida non sono utili. Ottenere le cose di base giuste può essere piuttosto difficile se non si conosce abbastanza bene la piattaforma.
Erik Schierboom,

119

(Corretto) Esiste una linea guida ufficiale, come ha suggerito Erik.

Quando vedo il TrySomethingmetodo, lo presumo

  • non getta
  • ritorna bool
  • se mi aspetto un valore, viene restituito tramite il parametro 'out'
  • esiste un Somethingmetodo che mi consente di gestire da solo ogni eccezione. (modifica, suggerito da Jesse Webb)

4
Correzione: ha linee guida ufficiali. Vedi la risposta di Erik.
nothrow

8
+1 Ma ho anche una quarta aspettativa: se esiste un TryFoometodo, ci sarà un Foometodo simile che mi permetterà di gestire qualsiasi `` eccezione ''. Le firme di questi metodi saranno probabilmente diverse, quindi i loro usi non sono intercambiabili senza altre modifiche al codice.
Jesse Webb,

1
@JesseWebb, grazie per averlo sottolineato. Ho aggiunto il tuo commento alla mia risposta, se non ti dispiace.
nothrow

1
"Non getta" mi sembra troppo generalizzato. Ad esempio, Int32.TryParse (String, NumberStyles, IFormatProvider, Int32) genera ArgumentException se non gli piace il parametro di stile.
Jirka Hanika,

Concordo sul fatto che "non gettare" potrebbe essere considerato troppo generalizzato, ma credo che l'intenzione fosse quella di comunicare che non si lanciava come risultato dell'esecuzione piuttosto che come risultato del valore dei parametri.
ConfusingBoat

8

Penso che dovresti usare tryquando vuoi procedere. Non importa che un metodo restituisca un valore o no.

Caso 1: se ritorna bene, puoi procedere in qualche modo.

Caso 2: se non ritorna: va ancora bene; puoi procedere in qualche altro modo.

E se ti aspetti un valore come output di quel metodo, usa il outparametro.

Esempio

int value
if (dictionary.TryGetValue("key", out value))
{
    // Proceed in some way
}
else
{
    // Proceed in some other way
}

6

Devi usare "Prova" nel nome del metodo, quando vuoi manifestare il fatto che l'invocazione del metodo può produrre risultati non validi. Seguire lo standard .NET, tra l'altro, non è una funzione che genera un'eccezione, ma la funzione che restituisce un valore VALIDo NON_VALID, dal punto di vista del programma, valore.

Alla fine, tutto questo sulla convenzione di denominazione che decidi di utilizzare nel tuo gruppo.


5

Assicurati di includere trynel tuo nome metodo se:

  • non fai alcuna eccezione
  • il tuo metodo ha la seguente firma: bool TrySomething(input, out yourReturn)

Quindi fondamentalmente se usiamo try-metodi otteniamo solo un risultato booleano.

Quindi il seguente codice non genererà alcuna eccezione:

string input = "blabla";
int number;
if (int.TryParse(input, out number))
{
// wooohooo we got an int!
} else
{
//dooh!
}

Considerando che questo codice può (e in questo caso) generare eccezioni:

string input = "blabla";
int number;
try
{
     number = int.Parse(input); //throws an exception
}
catch (Exception)
{
     //dooh!
}

L'uso dei metodi Try è un modo più sicuro e più difensivo per codificare. Inoltre, lo snippet di codice n. 2 richiede più prestazioni per essere eseguito se non è un numero intero.


Lo snippet di codice n. 2 dovrebbe essere letto int number = int.Parse(input);se si desidera che sia più significativo in questo contesto.
Pierre Arnaud,

@PierreArnaud Grazie, l'ho cambiato!
Fabian Bigler,

Manca ancora la int number;dichiarazione prima del blocco try e number = ...dell'assegnazione.
Pierre Arnaud,

@PierreArnaud Grazie, ho inserito anche 'numero int' ora.
Fabian Bigler,

Nota che puoi comunque generare eccezioni se l'eccezione non è in qualche modo correlata all'azione diretta eseguita, come TryLoadFile(path, out file)woah, dalla RAM. Quindi il chiamante non si aspetterebbe errori per un percorso errato o accesso negato, ma un'eccezione per le cose più bizzarre che potrebbero anche andare storto. E documentalo.
Luke Puplett,

0

Lo zio Bob fa l'esempio di seguito nel suo libro Clean Code . Ogni volta che ci aspettiamo che venga generata un'eccezione, possiamo usare il Tryprefisso per un nome di metodo:

public void sendShutDown()
{
    try{
        tryToShutDown();
    } catch (DeviceShutDownError e) {
        logger.log(e);            
    }
}

E poi (adattato):

private void tryToShutDown()
{
    //some code with no error handling, but
    //something might go wrong here
}

Il tryToShutDownmetodo non commette errori nella gestione, poiché questa è la responsabilità del sendShutDownmetodo.

Il TryParsemodello di Microsoft viola la linea guida del codice pulito che afferma che dovremmo evitare i parametri di output.

Se non stiamo sviluppando una nuova versione di C #, non dobbiamo attenerci a tutte le linee guida di Microsoft. A volte non sono i migliori.

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.