LINQ – Variabili temporanee con la parola chiave Let

L’uso di LINQ apre davvero a scenari molto molto interessanti grazie alla sua potenza e flessibilità.

Oggi ho scoperto che in una query LINQ è possibile costruire una variabile temporanea ed utilizzarla successivamente nella esposizione del risultato della query.

Ecco un esempio:

Nella query LINQ precedente, mediante la parola chiave “let” è possibile creare una variabile temporanea (discount nell’esempio), farci delle manipolazioni, e ritrovarsi la variabile nella query.

Figo

Object Identity / Equality

E’ noto che il metodo virtuale Equals ereditato da ogni oggetto dalla classe System.Object permette di definire un criterio di uguaglianza tra due oggetti non basato esclusivamente sulla reference (ovvero 2 oggetti sono uguali se puntano alla stessa istanza di un determinato oggetto).

E’ altresì noto che ridefinendo il metodo Equals siamo costretti a ridefinire il metodo GetHashCode per far si che in presenza di 2 oggetti uguali (Equals che ritorna true), il metodo GetHashCode ritorni lo stesso valore di hash per i 2 oggetti, questo perchè l’oggetto in questione potrebbe essere usato come chiave in una collezione di tipo HashTable o Dictionary<T,V>.

L’implementazione di GetHashCode fornita dalla classe System.Object fornisce un valore di hash distinto per ogni istanza di una data classe presente in un dato AppDomain, e tutto ciò è in linea con l’implementazione di Equals fornita da System.Object.

Ma se per un dato oggetto volessimo forzare l’uguaglianza per riferimento ?

Non basta usare ReferenceEquals(x, y) perchè, come detto, alcune classi come i dizionari utilizzano il metodo Equals per definire l’uguaglianza tra due oggetti (che di default si traduce in “identità” di un oggetto e non in “uguaglianza”).

Dovremmo ridefinire il medoto Equals in questo modo:

public override bool Equals(object obj) 
{ 
   return System.Object.ReferenceEquals(this, obj); 
}

ma in questo modo saremmo costratti ancha a ridefinire GetHashCode senza poter fornire l’implementazione standard di System.Object.

Questo problema si risolve utilizzando il medoto GetHashCode, ma quello fornito dalla classe System.Runtime.CompilersServices.RuntimeHelpers.

Questo metodo infatti, a dispetto del nome identito al metodo della classe System.Object, ritorna sempre un valore hash univoco per ogni istanza distinta di ogni oggetto in memoria, ovvero esattamente l’implementazione standard fornita da System.Object a prescindere se il metodo virtuale Object.GetHashCode sia o non sia ridefinito, ed adatta alla sola uguaglianza per riferimento.

Il tutto può essere inglobato in una classe Comparer apposita, in questo modo:

Raccolta extension methods

Gli extension methods sono una feature estremamente potente ed interessante, introdotta a partire dal .Net Framework 3.5 SP1.

A tal proposito, su Codeplex è presente un interessantissima libreria di codice che raccoglie extension methods applicati a svariati tipi.

Davvero molto molto utile.

Come detto qui da Gianluca Carucci, questa feature non necessita necessariamente della versione 3.5 del .Net Framework per essere utilizzata, ma, con un piccolo accorgimento, è possibile sfruttarne a pieno le potenzialità utilizzando anche il .Net Framework 2.0.

Pertanto, nella pagina Codeplex sopra citata, i “requirements” sono errati.

Link utili della settimana #1

MVVM Toolkit Light

Ajax Control Toolkit release 30930 (30 sett 2009);

thinktecture.WSCF.blue (Contract first WCF Tool)

– The ModelView-ViewModel design pattern for WPF

Code Run (questo è davvero incredibile, si evincono chiaramente le potenzialità del Cloud Computing).  Trattasi di un IDE Online, con cui è possibile sviluppare progetti .NET direttamente nel browser, potendo anche disporre di un ambiente di host on the cloud, su cui è possibile effettuare il deployment delle proprie applicazioni sviluppate on line.

Bonnie .NET API per sviluppare applicazioni che usano la crittografia della informazioni o certificati X.509

Invocazione di store procedure oracle in .NET

Il Data Access Application Block, contenuto all’interno della Enterprise Library 4.1 consente di richiamare store procedures passando esclusivamente il valore dei singoli parametri richiesti (mediante l’utilizzo del metodo GetStorepProcCommand dell’oggetto DatabaseFactory), nello stesso ordine con cui questi sono espressi nella firma della procedura. Poichè ADO .NET richiede comunque che ogni informazione in merito ai parametri della store sia obbligatoria (quindi tipo di dato, dimensione, precisione, scala, ecc), il metodo effettua internamente una chiamata al metodo DeriveParameters di ADO .NET che, attraverso un round-trip al database server, consente di recuperare tutte le informazioni necessarie sui parametri. Poichè come detto, questa chiamata richiede un round-trip verso il server, il data access application block fornisce anche un meccanismo di caching delle informazioni sui parametri recuperate dal server.

Oracle e SqServer hanno un meccanismo differente circa il ritorno di un resultset da una store procedure. Oracle infatti richiede, a differenza di Sql Server, l’utilizzo di un cursore come parametro di output per recuperare il resultset derivante da procedure che lo ritornano, fornendo anche un tipo speciale di dato, cursor appunto, nel suo provider nativo per .NET.

Se si usa il Data Access Application Block per invocare store procedure Oracle che ritornano un resultset attraverso l’uso di un cursore come parametro di output, non è necessario indicare quest’ultimo tra i parametri (anche perchè, pur provando ad indicarlo esplicitamente, non si troverebbe il tipo di dati cursor disponibile tra i tipi di dati in quanto viene usato l’enum System.Data.DbType che rappresenta genericamente i tpi di dati  per qualsiasi .NET Data Provider).

Basta infatti passare un generico parametro di output avente il valore null come primo parametro della store procedure Oracle e l’oggetto OracleDatabase farà il lavoro per noi. Questo oggetto infatti assume che il primo parametro di una store procedure sia un cursore di output per la restituzione del resultset

Le direttive using devono essere poste all’interno del namespace

Questo post inizia con una frase tratta da un post di Scott Hanselmann con cui mi trovo completamente d’accordo:

Don’t believe everything you read, even on a Microsoft Blog.             

Don’t believe this blog, either!

Decide  for yourself with experiments if you need a tiebreaker!

Credo sia proprio vero, mai fidarsi ciecamente di quello che si legge in giro, soprattutto quando seri dubbi farebbero pensare il contrario.

Il motivo è presto detto: utilizzo normalmente FxCop come strumento di analisi del codice sorgente, lo trovo molto completo e ben fatto. Spinto dalla curiosità ho voluto utilizzare Source Analysis, un tool gratuito fornito da Microsoft ed integrato nell’IDE di Visual Studio. Dopo la primissima prova fatta mi ha incuriosito una sua segnalazione:

SA1200 – All using directives must be placed inside of the namaspace.

Per farla breve, tutti i files sorgenti del mio progetto provocavano una segnalazione di questo tipo poichè le direttive using erano poste esternamente alla definizione del namespace, così come automaticamente viene creato uno scheletro di una classe all’interno dell’IDE. La segnalazione in questione invita invece ad includere le direttive using all’interno della definizione del namespace, semprecchè sia presente. Facendo qualche ricerca in giro ho scoperto che in questo modo il compilatore segnala immediatamente una eventuale ambiguità tra i nomi dei tipi creati all’interno del proprio namespace e i tipi presenti nei vari namespace del .NET Framework. E fin qui nulla di strano.

Ho scoperto inoltre che questa guideline servirebbe anche ad aumentare le prestazioni, almeno nei casi specifici, in quanto forzarebbe il “lazy loading” degli assembly e non il caricamento immediato. In altre parole, quando il viene invocato un metodo di una classe e viene compilato il codice “just in time” (JITTED) il lazy loading permette di caricare in memoria solo gli assembly referenziati che servono all’invocazione del metodo stesso, e non tutti gli assembly referenziati da una classe, a prescindere se utilizzati o no da una specifica invocazione di un metodo. Questo permette di caricare solo lo stretto necessario anche se una classe referenzia un assemby non utilizzato da un metodo.

Sinceramente non mi è venuto in mente un solo valido motivo per cui una direttiva using posta in un certo modo potesse influenzare l’attività del CRL a runtime, e sono rimasto alquanto dubbioso sulla effettiva validità. Prima che potessi avere il tempo di fare una prova specifica mi son trovato questo post di Scott Hanselmann, al quale rimando per una esauriente spiegazione, che dimostra come purtroppo ciò non sia affatto vero, cioè gli assembly referenziati vengono caricati tutti i memoria immediatamente, a prescindere se il metodo in questione li usa oppure no, ed a prescindere se le direttive using vengono poste all’interno o all’esterno della definizione di namespace.

Quindi la morale è: non credere mai a quello che leggi, neanche se lo leggi da questo blog :), ma sperimenta sempre.

Automatic properties in c# 3.0

Utilizzando C# 3.0 è possibile scrivere le proprietà di una classe in modo estremamente compatto, in questo modo:

Public string Nome {get; set;}

Questa modalità, chiamata “Automatic properties” permette quindi di omettere il riferimento al membro privato che normalmente viene “wrappato” dalla proprietà stessa.

Sarà compito del compilatore autogenerare al volo il membro privato al momento della compilazione. Questa caratteristica impone che il codice della classe non può in nessun modo accedere alla variabile privata, appunto perchè al momento della stesura del codice essa non esiste ancora in quanto sarà autogenerata in fase di compilazione. E’ quindi necessario utilizzare direttamente il nome della proprietà nel codice della classe per accedere al suo contenuto e/o modificarlo.

L’impossibilità del codice ad accedere alla variabile privata è dovuta al fatto che, poichè è possibile in qualsiasi momento tornare alla dichiarazione classica della proprietà indicando esplicitamente una variabile privata, è necessario assicurare al codice la piena compatibilità tra le due modalità. In altre parole, se si trasforma una “Automatic property” in una proprietà diciamo così “classica”, il codice che la utilizza continuerà a funzionare senza problemi perchè è certo che non avrà in nessun modo potuto utilizzare la variabile privata autogenerata. Per lo stesso motivo, non è possibile indicare un solo “accessor” per la proprietà ma dovranno essere indicati obbligatoriamente entrambi (get; set;), fermo restando che è sempre possibile indicare un ambito di visibilità diverso tra i due “accessor” (es. get; con visibilità public e set; con visibilità private)

Extentions Methods, come crearli

Una delle più interessanti feature disponibili con la versione 3.5 del .NET Framework sono, a mio avviso, gli Extention Methods, caratteristica legata al linguaggio di programmazione che permette di aggiungere metodi personalizzati a qualsiasi classe/interfaccia del .NET Framework, incluse le classi usate come classi di base (un esempio per tutte: la classe object),  “estendendo” appunto il tipo originale.

In tal modo è possibile estendere il contratto pubblico  esposto dalla classe /interfaccia senza per questo ricorrere all’ereditarietà. Utilizzando invece quest’ultima tecnica si era limitati alle solo classi ereditabili (non dichiarate “sealed”, come ad esempio la classe System.String), e soprattutto si correva il rischio di compromettere la consistenza dell’oggetto nel caso in cui facendo l’override di un metodo ci si dimenticava di richiamare il corrispondente metodo della classe di base.

A volte molti programmatori ricorrono all’ereditarietà per la semplice esigenza di aggiungere propri metodi ad una classe, non certo per ridefinire il comportamento della classe di base.

Inoltre, l’Intellisense di Visual Studio fornisce pieno supporto per gli Extention Methods, visualizzandoli correttamente all’interno del tipo che estendono, con una icona personalizzata.

Guardando i numerosi esempi di “Extention methods” disponibili sulla rete ho notato però che questi metodi sono inclusi in una classe avente un namespace custom, esempio Mycomponent.Extentions.StringExtentions per gli extention methods della classe String. Questo è a mio avviso un errore, in quanto così facendo l’Intellisense di Visual Studio non mostra gli Extention Methods di una certa classe se il relativo namespace non viene importato (cosa ovvia). Questo comportamento sicuramente disorienta, in quanto dato un certo tipo la lista dei suoi metodi visualizzata è parziale.

Quindi, gli Extention Methods di un tipo dovrebbero essere raggruppati un una classe inserita nello stesso namespace del tipo che estendono. Nell’esempio precedente per estendere la classe System.String la relativa classe statica dovrebbe essere inclusa nel namespace System.

In questo modo, importando un solo namespace sono visibili sia i metodi pubblici che i metodi estesi.

D’altronde, questo è il comportamento dello stesso Framework. Ad esempio tutti gli Extentions Methods della classe System.Data.DataTable sono racchiusi nella classe DataTableExtentions inserita nel namespace System.Data.