I parametri di output sono utilizzabili tramite la keyword out e permettono di passare i parametri per riferimento. Hanno la caratteristica di non dover essere inizializzati prima della chiamata e che verranno valorizzati forzatamente dal metodo che li accetta.
Vediamo un esempio di dichiarazione e utilizzo dei parametri di output:
public void MioMetodo(out string parametro1)
{
parametro1 = "Almeno una assegnazione è obbligatoria prima di uscire dal metodo";
}
public void Main()
{
string stringaNonInizializzata;
MioMetodo(out stringaNonInizializzata);
// a questo punto il valore della stringa è inizializzato
}
Nulla vieta però di scrivere:
public void Main()
{
string stringaInizializzata = "Valore di default";
MioMetodo(out stringaNonInizializzata);
// a questo punto il valore di default è stato modificato
}
In questo caso però bisogna stare attenti al fatto che il valore di default verrà sicuramente perso durante l'esecuzione di del metodo MioMetodo.
Un esempio di utilizzo dei parametri di output da parte del framework .NET si trova nei vari metodi TryParse, uno dei quali è quello relativo agli interi int.TryParse.
I metodi di TryParse permettono di evitare i blocchi try-catch, necessari invece se si utilizza i più classici metodi Parse e sono quindi molto più comodi.
Vediamo quindi che invece di utilizzare int.Parse:
int numero;
try
{
numero = int.Parse("1");
}
catch (FormatException)
{
numero = 0;
}
catch (OverflowException)
{
numero = 0;
}
è possibile utilizzare int.TryParse e scrivere qualcosa di molto più semplice:
int numero;
int.TryParse("1", out numero);
in quanto TryParse non solleva alcuna eccezione.
Molto meglio, no? Abbiamo scritto molto meno codice e il tutto è molto più leggibile.
Ma se la stringa che viene passata non rappresenta un numero, come è possibile gestire un valore di default nei casi di errore di parsing?
Una prima sbadata e sbagliata soluzione è scrivere qualcosa del tipo:
int numero = -2; //il mio valore di default
int.TryParse("1", out numero);
perchè come ho già mostrato precedentemente tale valore verrà in ogni caso modificato dal metodo TryParse. La cosa ottimale è testare il valore booleano di ritorno e di conseguenza impostare il nostro valore di default:
int numero;
if (int.TryParse("1", out numero) == false)
{
numero = -2; //il mio valore di default
}
Attenzione quindi a non compiere come me l'errore di inizializzare il parametro di tipo out con il valore di default prima della chiamata, ma ricordate di farlo dopo, andando a testare il valore di ritorno. E' una piccola distrazione che può causare bugs difficili poi da scovare se non a colpi di debug.