domenica 27 settembre 2009

Validazione di DateTimeOffset con Enterprise Library Validation Application Block

Il tipo di dato DateTimeOffset è stato introdotto con .NET Framework 3.5 ed è simile a DateTime ma ha il vantaggio di aggiungere le informazioni di offset dal GMT in modo da poter legare una data ad un certo fuso orario.

Ho iniziato quindi ad utilizzarlo al posto del classico DateTime per ogni data che avesse bisogno anche delle informazioni del fuso orario. Ovviamente ho continuato ad usare DateTime per tutte le date che hanno un valore slegato dal fuso orario, ad esempio l'orario di apertura di un negozio.
Per dettagli sull' utilizzo di DateTimeOffset rimando a questo post del team BCL.

Per quanto riguarda la validazione di DateTimeOffset ho avuto qualche problema.
Solitamente per la validazione utilizzo il comodissimo Validation Application Block della libreria Entrprise Library, purtroppo però non esiste il corrispondente di DateTimeRangeValidator per DateTimeOffset.

Ho provato ugualmente ad utilizzare DateTimeRangeValidator con il tipo DateTimeOffset ma ho ricevuto il seguente messaggio: "Value to validate is not of the expected type: expected System.DateTime but got System.DateTimeOffset instead".

Ho pensato allora di chiedere se esiste qualcosa a rigurardo sul forum di Entreprise Library ed ho avuto una veloce e risolutiva risposta che illustra come implementare un custom RangeValidator per il tipo DateTimeOffset. Funziona perfettamente. Peccato solamente non averci pensato da solo.

E' possibile recuperare il codice dalla discussione stessa.

giovedì 27 agosto 2009

Bloggers: Win a free place for Roy Osherove’s TDD Masterclass (worth £2395!)


Roy Osherove is giving an hands-on TDD Masterclass in the UK, September 21-25. Roy is author of "The Art of Unit Testing" (http://www.artofunittesting.com/), a leading tdd & unit testing book; he maintains a blog at http://iserializable.com (which amoung other things has critiqued tests written by Microsoft for asp.net MVC - check out the testreviews category) and has recently been on the Scott Hanselman podcast (http://bit.ly/psgYO) where he educated Scott on best practices in Unit Testing techniques. For a further insight into Roy's style, be sure to also check out Roy's talk at the recent Norwegian Developer's Conference (http://bit.ly/NuJVa).

Full Details here: http://bbits.co.uk/tddmasterclass.

bbits are holding a raffle for a free ticket for the event. To be eligible to win the ticket (worth £2395!) you MUST paste this text, including all links, into your blog and email Ian@bbits.co.ukwith the url to the blog entry. The draw will be made on September 1st and the winner informed by email and on bbits.co.uk/blog.

I wish to win!

mercoledì 15 luglio 2009

TryParse, parametro di output e valore di default


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.