Domanda

Non capisco se deve essere utilizzato un parametro di output, io personalmente avvolgo il risultato in un nuovo tipo se ho bisogno di tornare più di un tipo, trovo che molto più facile da lavorare rispetto fuori.

Metodo

Ho visto come questo,

   public void Do(int arg1, int arg2, out int result)

Ci sono dei casi in cui che in realtà ha un senso?

come su TryParse, perché non restituire un tipo ParseResult? o nel quadro più recente restituire un tipo zero-grado?

È stato utile?

Soluzione

Out è buono quando si dispone di una funzione di TryNNN ed è chiaro che l'out-parametro sarà sempre impostato anche se la funzione non riesce. In questo modo ci si basa sul fatto che la variabile locale si dichiara verrà impostata piuttosto che dover mettere controlli più avanti nel codice contro nullo. (Un commento qui sotto indica che il parametro potrebbe essere destinata a null, quindi si consiglia di verificare la documentazione per la funzione che si sta chiamando per essere sicuro se questo è il caso o meno.) Si rende il codice un po 'più chiaro e più facile leggere. Un altro caso è quando si ha bisogno di restituire alcuni dati e lo stato delle condizioni del metodo come:

public bool DoSomething(int arg1, out string result);

In questo caso il ritorno può indicare se la funzione è riuscita e il risultato viene memorizzato nel parametro out. Certo, questo esempio è artificioso perché è possibile progettare un modo in cui la funzione restituisce semplicemente un string, ma si ottiene l'idea.

Uno svantaggio è che si deve dichiarare una variabile locale per usarli:

string result;
if (DoSomething(5, out result))
    UpdateWithResult(result);

Al posto di:

UpdateWithResult(DoSomething(5));

Tuttavia, che potrebbe anche non essere uno svantaggio, dipende il disegno che si sta andando per. Nel caso di DateTime, entrambi mezzi (Parse e TryParse) sono forniti.

Altri suggerimenti

Beh, come con la maggior parte delle cose dipende. Vediamo le opzioni

  • si potrebbe tornare quello che vuoi come valore di ritorno della funzione
  • se si vuole restituire più valori o la funzione ha già un valore di ritorno, è possibile utilizzare il params o creare un nuovo tipo composito che espone tutti questi valori come proprietà

Nel caso di TryParse, utilizzando un parametro out è efficiente - non dovete creare un nuovo tipo che sarebbe 16B di overhead (su 32b macchine) o sostenere il costo perf di averli spazzatura posta raccolti la chiamata. TryParse potrebbe essere chiamato da all'interno di un ciclo, per esempio - così fuori params regola qui
. Per le funzioni che non sarebbe chiamato all'interno di un ciclo (cioè le prestazioni non è una grande preoccupazione) corrispondente un unico oggetto composto potrebbe essere 'pulito' (personale per chi guarda). Ora, con i tipi anonimi e tipizzazione dinamica, potrebbe diventare ancora più facile.

Nota:

  1. params out hanno alcune regole che devono essere seguite cioè il compilatore garantisce che la funzione fa inizializzare il valore prima di uscire. Così TryParse deve impostare il parametro ad un certo valore, anche se non è riuscita operazione di analisi
  2. Il modello TryXXX è un buon esempio di quando utilizzare il params - Int32.TryParse è stato introdotto coz persone si sono lamentati della hit perf di catturare eccezioni sapere se parse non è riuscita. Anche la cosa più probabile che faresti in caso parse riuscito, è quello di ottenere il valore analizzato - utilizzando un param out significa che non c'è bisogno di effettuare un'altra chiamata metodo per analizzare

Credo che fuori è utile per le situazioni in cui è necessario restituire sia un valore booleano e un valore, come TryParse, ma sarebbe bello se il compilatore avrebbe permesso una cosa del genere:

bool isValid = int.TryParse("100", out int result = 0);

Sicuramente, fuori i parametri sono destinati ad essere utilizzati quando si dispone di un metodo che ha bisogno di restituire più di un valore, nell'esempio che avete inviato:

public void Do(int arg1, int arg2, out int result)

E non si rende molto senso usare un parametro out, dal momento che sono solo restituendo un valore, e che il metodo potrebbe essere utilizzato meglio se si rimuove il parametro fuori e mettere un valore int di ritorno:

public int Do(int arg1, int arg2)

Ci sono alcune cose buone di fuori dei parametri:

  1. I parametri di output sono inizialmente considerati non assegnato.
    • Ogni parametro di deve essere definitivamente assegnato prima che il metodo restituisce, il codice non compilerà se si perde un incarico.

In conclusione, ho praticamente Prova Usa fuori params nel mio API private per evitare di creare tipi diversi di avvolgere più valori di ritorno, e il mio API pubblica, li uso solo su metodi che corrispondono con la TryParse modello.

Anni di ritardo con una risposta, lo so. fuori (e ref pure) è anche molto utile se non si desidera il tuo metodo non istanziare un nuovo oggetto per tornare. Questo è molto importante nei sistemi ad alte prestazioni in cui si desidera ottenere prestazioni microsecondo sub per il metodo. istanziazione è relativamente costoso visto da una prospettiva accesso alla memoria.

Creazione di un tipo solo per i valori di ritorno suona poco doloroso per me :-) Prima dovrò creare un tipo per restituire il valore poi nel metodo chiamante ho assegnare il valore dal tipo restituito alla variabile reale che ne ha bisogno.

Out parametri sono simipler da usare.

Sì, ha senso. Prendete questo per esempio.

String strNum = "-1";
Int32 outNum;

if (Int32.TryParse(strNum, out outNum)) {
    // success
}
else {
    // fail
}

Che cosa si potrebbe tornare se l'operazione non è riuscita in una funzione normale con un valore di ritorno? Tu certamente non poteva tornare -1 per rappresentare un fallire, perché allora non ci sarebbe alcuna differenza tra il valore di fail-ritorno e il valore effettivo che veniva analizzato per cominciare. Questo è il motivo per cui si ritorna un valore booleano per vedere se è riuscito, e se lo ha fatto allora abbiamo il nostro valore "ritorno" in modo sicuro assegnato già.

E mi infastidisce che non posso passare null per il parametro per le funzioni TryParse.

Ancora, io lo preferisco, in alcuni casi per la restituzione di un nuovo tipo con due pezzi di dati. Soprattutto quando sono estranei per la maggior parte o un pezzo è necessaria solo per una singola operazione un attimo dopo. Quando ho bisogno di salvare il valore risultante di una funzione TryParse mi piace molto avere un parametro fuori piuttosto che qualche classe ResultAndValue casuale che ho a che fare.

Se si crea sempre un tipo, allora si può finire con un sacco di confusione nella vostra applicazione.

Come detto qui, un tipico caso d'uso è un metodo TrySomething in cui si desidera restituire un bool come indicatore di successo e quindi il valore effettivo. Trovo anche che un po 'più pulita in un'istruzione if--. Tutte e tre le opzioni hanno all'incirca lo stesso LOC comunque

int myoutvalue;
if(int.TryParse("213",out myoutvalue){
    DoSomethingWith(myoutvalue);
}

vs.

ParseResult<int> myoutvalue = int.TryParse("213");
if ( myoutvalue.Success ) {
    DoSomethingWith(myoutvalue.Value);
}

vs.

int? myoutvalue = int.TryParse("213");
if(myoutvalue.HasValue){
    DoSomethingWith(myoutvalue.Value);
}

Per quanto riguarda il "Perché non restituire un tipo Nullable": TryParse esiste dal 1.x quadro, mentre i tipi Nullable è venuto con 2.0 (in quanto richiedono Generics). Allora, perché la compatibilità pausa unneccessarily o avviare l'introduzione di incoerenze tra TryParse su alcuni tipi? È sempre possibile scrivere il proprio metodo di estensione per duplicare le funzionalità già esistente (vedere Eric Lipperts Messaggio su un argomento non correlato che include qualche ragionamento dietro a fare / non fare cose)

Un altro caso d'uso è se si deve restituire più valori estranei, anche se se si fa questo che dovrebbe far scattare un allarme che il vostro metodo è forse facendo troppo. D'altra parte, se il metodo è qualcosa di simile a un database o web chiamata di servizio costoso e si desidera memorizzare nella cache il risultato, può avere senso per farlo. Certo, si potrebbe creare un tipo, ma ancora una volta, questo significa un tipo di più nella vostra applicazione.

Io uso il parametri volte per facilitarne la lettura, quando si legge il nome del metodo è più importante che qualunque sia l'uscita del metodo è-particolarmente per i metodi che eseguono i comandi, oltre a restituire i risultati.

StatusInfo a, b, c;

Initialize(out a);
Validate(a, out b);
Process(b, out c);

vs.

StatusInfo a = Initialize();
StatusInfo b = Validate(a);
StatusInfo c = Process(b);

Almeno per me, ho messo molta enfasi sui primi caratteri di ogni riga quando sto scansione. Posso facilmente dire che cosa sta succedendo nel primo esempio dopo aver riconosciuto che alcune variabili "StatusInfo" sono dichiarati. Nel secondo esempio, la prima cosa che vedo è che un gruppo di StatusInfo viene recuperato. Devo eseguire la scansione di una seconda volta per vedere che tipo di effetti i metodi possono avere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top