lunedì 8 giugno 2009

Le novità di Visual Basic 2010 - Il linguaggio, seconda parte

 

Le novità di Visual Basic 2010 - Il linguaggio, seconda parte
a cura di Alessandro Del Sole (requisiti: conoscenza intermedia del linguaggio Visual Basic 2008 )

Introduzione
Nel precedente articolo abbiamo iniziato a parlare delle novità del linguaggio Visual Basic 2010, sfruttando l'attuale Beta 1. Abbiamo anche detto che, trattandosi della prima Beta, potrebbero esserci delle modifiche in futuro ma che questa circostanza è abbastanza remota in quanto si tratta di innovazioni presenti fin dalla CTP di ottobre 2008. Le novità introdotte la volta scorsa sono le seguenti:

  • Auto-implemented properties
  • Implicit line continuation
  • Optional nullable parameters
  • Collection initializers
  • Array literals

In questo terzo articolo della mini-serie dedicata a Visual Basic 2010, proseguiremo la carrellata sulle novità relative al linguaggio e analizzeremo le novità un pochino più complesse, ma che senza dubbio rendono più potente il linguaggio stesso. Nell'area download di VB T&T è disponibile il progetto sorgente completo, a corredo di questo e del precedente articolo. Ovviamente, per poterlo utilizzare dovete aver installato la Beta 1 di Visual Studio 2010.

Espressioni lambda multi-linea e statement lambda
In Visual Basic 2010 il concetto delle espressioni lambda è stato ripreso e notevolmente potenziato. Rispetto alla versione 2008, infatti, è possibile utilizzare delle espressioni multilinea nonché la parola chiave Sub, oltre a Function, per poter generare delegati anonimi al volo che non restituiscano valori.

Facciamo un esempio ed ipotizziamo di voler ottenere l'elenco dei processi attivi sul sistema, il cui nome inizi con la lettera A. In Visual Basic 2008 avremmo potuto scrivere:

    'Sintassi VB 2008
Dim processes = Process.GetProcesses.Where(Function(p) p.ProcessName.StartsWith("A"))


Utilizziamo quindi una Function direttamente in linea, che restituisce un insieme di processi. In Visual Basic 2010 è stato fatto un grande progresso. Potremmo infatti trasformare la richiesta sopra evidenziata in questo modo:



    'Sintassi VB 2010
Dim processes = Process.GetProcesses.Where(Function(p)
Try
Return p.ProcessName.
StartsWith("A")
Catch ex As Win32Exception
'in caso di errore fai qualcosa
End Try
End Function)


Naturalmente VB 2010 consente anche la vecchia sintassi, ma ora permette di generare veri e propri metodi all'interno dei quali si possono inserire blocchi di codice anche complessi, secondo il classico stile Function.. End Function. Nell'esempio, poiché stiamo lavorando sui processi, è utile intercettare una Win32Exception che potrebbe verificarsi se un processo non consente l'accesso alle proprie informazioni. In questo modo, possiamo prevedere questo scenario, circostanza non consentita in VB 2008 all'interno della lambda.



Sempre rimanendo sull'esempio dei processi attivi, proviamo a scandire la collezione ottenuta per visualizzare il nome del processo. In Visual Basic 2010 è ora consentito scrivere quanto segue:



    processes.ToList.ForEach(Sub(p) Console.WriteLine(p.ProcessName))


Oltre a sfruttare un metodo ForEach della collezione List(Of T), notate come sia possible utilizzare una lambda che non restituisca nulla, attraverso la parola Sub, altra novità di VB definita Statement Lambda. Ovviamente, anche in questo caso è possibile suddividere l'espressione su più righe:



    processes.ToList.ForEach(Sub(p)
Console.WriteLine("Process name:")
Console.WriteLine(p.ProcessName)
Console.WriteLine()
End Sub)


Si tratta di una grande caratteristica che rende molto potente e versatile il nostro linguaggio, che potremo particolarmente apprezzare con LINQ per l'accesso ai dati.



Varianza generica: Covariance e Contravariance


La varianza generica è un concetto fortemente legato all'ereditarietà tra classi e comporta un discorso suddividibile in due parti: covarianza e controvarianza. Iniziamo con lo spiegare la covarianza. Immaginiamo di avere una lista di stringhe, come la seguente:



    'uso i collection initializer
Dim someStrings As New List(Of String) From {"This ", "is ", "a string"}


Com'è noto, String eredita da System.Object. Dovremmo quindi essere in grado di assegnare un elenco di stringhe anche a un elenco generico di Object. Tuttavia, questo fino a VB 2008 non era consentito. In Visual Basic 2010 invece possiamo scrivere:



    Dim variance As IEnumerable(Of Object) = someStrings


Questa assegnazione è ora lecita. E' però consentita solo nei confronti di IEnumerable(Of T), infatti, se provassimo a fare la stessa cosa nei confronti di una List(Of T) (nel nostro caso List(Of Object)), il compilatore solleverebbe un messaggio di errore e ci inviterebbe ad utilizzare IEnumerable.



Se ora provassimo a scandire la collezione variance (che contiene un elenco di Object), otterremmo effettivamente l'esatta concatenazione di stringhe:



    Dim builder As New StringBuilder
For Each s In variance
builder.Append(s)
Next
MessageBox.Show(builder.ToString)


La covarianza, quindi, ci consente di ottenere il risultato previsto dalle classi derivate nell'ambito di una collezione di oggetti di tipo astratto. La controvarianza, invece, 'ragiona' essenzialmente al contrario: da una classe derivata ci consente di sfruttare la classe astratta.



Ipotizziamo di avere un'applicazione Windows Forms in cui ci sia un pulsante, del quale vogliamo gestire gli eventi MouseClick e KeyUp. Tali eventi sono gestiti da metodi che ricevono, come argomenti, rispettivamente oggetti di tipo MouseEventArgs e KeyEventArgs. Entrambi questi ultimi, però, ereditano da System.EventArgs. Ciò posto, è possibile scrivere un gestore di evento unico, che sfrutti EventArgs, come nel modo seguente:



    AddHandler ContravarianceButton.MouseClick, AddressOf CommonHandler
AddHandler ContravarianceButton.KeyUp, AddressOf CommonHandler


  Private Sub CommonHandler(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("You did something!")
End Sub


Grazie alla controvarianza, quindi, abbiamo potuto sfruttare la classe astratta per gestire il comportamento di classi derivate. Potete verificare il funzionamento del codice facendo clic sul pulsante oppure premendo un tasto quando il pulsante stesso ha il focus.



Distribuzioni per Office senza assembly per l'interoperabilità primaria


Con l'attuale versione di .NET Framework, la 3.5 Service Pack 1, e dei linguaggi .NET, nel momento in cui facciamo riferimento ad assembly che ci consentono di interagire con le applicazioni della suite di Microsoft Office dobbiamo poi includere nelle nostre distribuzioni (ClickOnce o Windows Installer) anche gli assembly per l'interoperabilità primaria. Questo può non essere comodo sempre; infatti, includere tali assembly può essere dispendioso in termini di spazio, soprattutto se magari abbiamo utilizzato solo pochi oggetti di quel particolare assembly.



Con il .NET Framework 4.0, e quindi con Visual Basic 2010, è stata introdotta una brillante soluzione: è possibile omettere di includere gli assembly per l'interoperabilità con Office e far sì che, all'interno del nostro eseguibile, siano incorporati i soli oggetti di cui effettivamente facciamo utilizzo.



Supponiamo, a esempio, di avere un'applicazione con un riferimento all'assembly Microsoft.Office.Interop.Word.dll, per la creazione di oggetti utilizzabili da Microsoft Word. All'interno della nostra applicazione abbiamo questo codice, che istanzia un oggetto di tipo Microsoft.Office.Interop.Word.Document, corrispondente a un documento di Word:



    Dim WordDoc As New Microsoft.Office.Interop.Word.Document
'Segue codice di creazione del documento


Stiamo quindi utilizzando il solo oggetto Document. Includere nella nostra distribuzione anche il relativo assembly per l'interoperabilità può essere uno spreco in termini di spazio. Andiamo quindi in Solution Explorer e attiviamo la visualizzazione di tutti i file, quindi espandiamo l'elenco dei riferimenti. Selezioniamo l'assembly Microsoft.Office.Interop.Word.dll e, nella finestra delle proprietà, impostiamo la proprietà Embed Interop su True, come nella figura a destra.



Così facendo, l'assembly non verrà incluso nella distribuzione mentre, nel nostro assembly, verrà incorporata la definizione dell'oggetto Document e ciò che serve al suo utilizzo. Possiamo verificare che quanto detto è effettivamente vero utilizzando Microsoft IL Disassembler (figura sottostante):





Se invece facciamo utilizzo di molti tipi definiti nell'assembly, potrebbe essere conveniente includerlo nella distribuzione impostando la proprietà Embed Interop su False.



Interoperabilità con linguaggi dinamici


Visual Basic 2010, ma più in generale Visual Studio, offre il supporto al Dynamic Language Runtime, una nuova infrastruttura che consente, mediante late-binding, l'interoperabilità tra linguaggi di programmazione 'statici' come Visual Basic o C# e linguaggi 'dinamici', come IronPython per .NET che espongono, tra l'altro, funzionalità di scripting.



Grazie al DLR, quindi, è possibile fare uso di codice di un linguaggio dinamico all'interno del codice Visual Basic. Facciamo un esempio, prendendo in considerazione l'attuale versione di IronPython per .NET, implementazione del linguaggio Python realizzata da Microsoft e scaricabile dal sito CodePlex, la comunità per progetti open-source. IronPython, oltre ad una serie di documenti esplicativi, è distribuito con diversi file di codice di esempio. Ovviamente in questa sede non ci interessa introdurre IronPython, né imparare a utilizzarlo; piuttosto ci interessa capire come sia possibile utilizzarne il codice per futuri approfondimenti. Dopo aver scaricato e installato IronPython.NET, possiamo predisporre una piccola dimostrazione, per esempio creando un nuovo progetto per la Console. Fatto questo, aggiungiamo un riferimento agli assembly IronPython.dll, IronPython.Modules.dll, Microsoft.Scripting.dll, tutti locati nella cartella di installazione di IronPython.



A questo punto dobbiamo aggiungere al progetto il file di codice Python che intendiamo utilizzare nella nostra applicazione. Utilizzando il comando Project|Add existing item, andiamo a reperire il file chiamato First.py all'interno della cartella di installazione di IronPython. Questo file di codice Python definisce alcuni semplicissimi metodi e, come il nome lascia intendere, ha lo scopo di introdurre il linguaggio. Una volta aggiunto questo file al progetto, dobbiamo impostarne la proprietà Build Action su Copy Always all'interno della Finestra delle Proprietà.



Fatto questo, dobbiamo necessariamente impostare Option Strict su Off, poiché, come accennato all'inizio, questo tipo di lavoro si fa sfruttando il late-binding, tecnica non consentita da Option Strict On. Quindi aggiungiamo alcune direttive Imports, che ci permettono di abbreviare il richiamo ad alcune classi:



Imports IronPython
Imports IronPython.Hosting
Imports Microsoft.Scripting.Hosting


Il file First.py espone un metodo chiamato Sum, che restituisce il risultato della somma di due numeri. Quindi ipotizziamo di voler fare uso di questo metodo per mostrare il risultato di un'addizione. In primo luogo, iniziamo con lo scrivere il seguente codice:



  Sub Main()

'Tramite ScriptRuntime ottiene l'hosting di Python
Dim py As ScriptRuntime = Python.CreateRuntime

'late-binding: il metodo UseFile legge il contenuto
'del file di codice Python
Dim test As Object = py.UseFile("first.py")


Tramite l'oggetto py di tipo ScriptRuntime possiamo ottenere l'istanza del runtime Python. Py espone un metodo chiamato UseFile, che ci permette di specificare quale file di codice Python vogliamo utilizzare, nel nostro caso quello chiamato first.py. Il risultato della lettura è assegnato all'oggetto test che ci consente di utilizzare i membri definiti nel codice Python. Ad esempio, possiamo ottenere il risultato desiderato in questo modo:



    'invoca il metodo Add definito nel file Python
'e assegna il risultato
Dim sum As Object = test.add(2, 4)

'mostra il risultato convertito da Object a Int32
Console.WriteLine(CInt(sum))
Console.ReadLine()

End Sub


Se avviamo l'applicazione, otterremo il risultato corretto della somma dei numeri 2 e 4. Chiaramente, il Dynamic Language Runtime non funziona solo con IronPython ma anche con altri linguaggi, come ad esempio IronRuby, altra implementazione .NET creata da Microsoft.



Conclusioni


Visual Basic 2010 è un linguaggio molto potente, che raggiunge un livello di maturità senza precedenti. Le novità del linguaggio, la co-evoluzione con Visual C# e il miglioramento della coding experience ci consentono di sviluppare applicazioni potenti e versatili per tutte le tecnologie .NET, migliorando il nostro lavoro sia attraverso il linguaggio stesso sia attraverso la strumentazione di Visual Studio 2010. Potete come di consueto contattarmi al mio indirizzo di posta elettronica o visitare il mio blog.



Risorse utili


Riporto, anche in questo articolo, un elenco di link a risorse utili che vi serviranno per iniziare a prendere confidenza con Visual Studio 2010 Beta 1, partendo dai download fino alle risorse di apprendimento:






Le novità di Visual Basic 2010 - Il linguaggio, seconda parte

Nessun commento:

Posta un commento