• Regolamento Macrocategoria DEV
    Prima di aprire un topic nella Macrocategoria DEV, è bene leggerne il suo regolamento. Sei un'azienda o un hosting/provider? Qui sono anche contenute informazioni per collaborare con Sciax2 ed ottenere l'accredito nella nostra community!

Guida Tutto Sul C#

Mascara4ever

Utente Mitico
Autore del topic
16 Novembre 2009
8.617
89
Miglior risposta
0
Introduzione a C#​
C#, si legge «c sharp», può essere considerato il linguaggio di programmazione per eccellenza del Framework .NET: diversamente dagli altri linguaggi, come Visual Basic o C++, esso è nato espressamente per la nuova piattaforma. In questo senso, è significativo il fatto che Microsoft stessa si sia servita di C# per scrivere gran parte delle librerie di .NET .

Uno degli slogan che hanno accompagnato C# fin dalla sua nascita lo presenta come «un linguaggio facile come Java, potente come il C++». In effetti, come vedremo, le somiglianze con i due linguaggi sono molte, e non solo dal punto di vista della sintassi.

Le differenze comunque ci sono ma la loro trattazione esula dagli obiettivi di questo corso, che si propone, invece, di analizzare nello specifico il linguaggio C#.

Chi fosse interessato a differenze e somilgianze, può trovare maggiori informazioni usando i collegamenti a fine lezione (in lingua inglese) oppure, avendo a disposizione Visual Studio 2005, si possono trovare maggiori dettagli sull'argomento cercando «Comparison Between Java and C#» e «Comparison Between C++ and C#» nella guida in linea.

Questa guida, in una prima fase, introdurrà ai concetti chiave di questo linguaggio, nella seconda parte del corso invece, ci si concentrerà sull'ambiente di sviluppo Visual Studio 2005 e sulle nuove funzionalità introdotte dalla versione 2.0 del Framework. Infine fornirà una panoramica degli strumenti messi a disposizione per la realizzazione di applicazioni web con ASP .NET.

Il corso si rivolge a chi ha già dimestichezza con la programmazione ad oggetti e con linguaggi simili a Java o C++.

Sono volutamente tralasciate le spiegazioni sulla sintassi di base: per esempio i costrutti if, switch, for, while, etc. Chi già conosce linguaggi come c++, Java, php o Javascript non vedrà grosse novità. Chi invece non avesse familiarità con i linguaggi cosiddetti "c-like" può trovare in fondo alla lezione un link per approfondire.

In ogni caso, dove necessario per la comprensione del corso, saranno indicati esplicitamente i collegamenti con i concetti trattati su altre fonti.

In queste prime pagine ci occuperemo delle caratteristiche proprie di C# e delle innovazioni che introduce nel modo di programmare.

Al momento della stesura di questa guida, il Framework .NET 2.0 e Visual Studio 2005 sono ancora in fase di beta test (in particolare, è stato usato Visual Studio 2005 Beta 2), quindi è possibile, anche se in linea di massima non dovrebbe accadere, che alcune delle caratteristiche mostrate saranno diverse dalla versione finale.

Poiché la versione italiana verrà rilasciata solo dopo il rilascio ufficiale del prodotto, si è fatto riferimento alle voci dei menù e delle finestre della versione inglese; ove possibile, è stata fornita una traduzione, che però in alcuni casi potrebbe non corrispondere con l'effettiva localizzazione in italiano.

Questa guida si propone di suscitare curiosità sul mondo di C#, fornendo però gli strumenti minimi necessari ad approfondire individualmente gli argomenti affrontati.

C# e VB .NET a confronto​
C# e Visual Basic .NET sono due tra i molti linguaggi di programmazione disponibili per la piattaforma .NET. Il Common Language Runtime (CLR) del Framework .NET costituisce, infatti, una piattaforma di esecuzione comune per un gran numero di linguaggi, tra cui C++, J#, Cobol.NET .

Più che stabilire quale sia il "migliore", è interessante capire le peculiarità di ciascun linguaggio. Ci soffermeremo sulla valutazione delle differenze più importanti.

Ad una prima analisi è evidente che VB.NET risulta la scelta preferita per chi proviene dalle versioni precedenti di VB e ASP-VBScript, mentre C# è più accattivante per chi proviene da esperienze con C++ e Java. La sintassi di C# assomiglia moltissimo a quella di Java, mentre quella di VB.NET è evoluzione del Visual Basic.

La differenza più importante nel passaggio dal vecchio al nuovo non riguarda tanto la sintassi quanto la sensazione di novità in termini di approccio alla programmazione ad oggetti.

Chi è abituato a lavorare in C++ o Java trova un ambiente in cui i concetti sono analoghi quando non del tutto sovrapposti. Per esempio in .NET come in Java tutto è un oggetto: è abbandonato ogni tipo di approccio ibrido con la programmazione strutturata in stile C++.

Quindi chi proviene dai "vecchi" ASP e VB si trova davanti ad un linguaggio simile in alcuni aspetti della sintassi di base ma con un approccio alla programmazione a oggetti che è comune a tutto il Framework ed è più proprio di Java e compagnia.

C# è un linguaggio nuovo, mentre VB .NET porta con sé l'eredità di tutte le versioni precedenti di Visual Basic (la sintassi di VB .NET, seppur aggiornata con il supporto agli oggetti, è praticamente la stessa di quella di Visual Basic 4.0, rilasciato nell'ormai lontano 1996).

Un primo aspetto evidente è che il codice scritto in VB .NET risulta più lungo rispetto all'equivalente in C#. Consideriamo, per esempio, una funzione che prende in ingresso due numeri e ne calcola la media:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Un'altra grande differenza, forse la più evidente, è che C# è case sensitive, ovvero fa distinzione tra maiuscole e minuscole, mentre VB case insensitive: per C# le variabili nomePersona e NomePersona sono diverse, mentre per Visual Basic .NET sono la stessa.

Al di là delle differenze che riguardano la sintassi, C# permette di realizzare cose che in VB .NET non si possono fare, e viceversa. Ad esempio, C#, mostrando la sua derivazione dal C++, consente di utilizzare i puntatori, cosa che VB .NET non permette.

Alcune differenze architetturali sono state colmate con la versione 2.0 del Framework, che introduce anche per Visual Basic .NET l'overloading degli operatori (altra caratteristica che C# ha preso da C++) e la possibilità di documentare il codice scritto utilizzando il linguaggio XML. Infatti C# permette la documentazione delle classi usando dei tag nel codice in modo molto somigliante ai commenti per JavaDocs.

VB .NET, in particolare con la nuova versione del Framework, rende ancora più semplice e veloce la scrittura di applicazioni: tra i tanti esempi che si potrebbero fare a riguardo, citiamo il namespace My , che fornisce un rapido accesso a tutta una serie di proprietà e metodi di uso comune, consentendo uno sviluppo più efficiente.

Le informazioni contenute nel namespace My sono comunque disponibili anche da C#, ma la sua presenza in VB .NET rende molto più agevole lo svolgimento di alcuni compiti. Ad esempio, per scaricare un file da Internet, usando Visual Basic .NET con il Framework 2.0 è sufficiente un'istruzione:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
In C# non esiste un oggetto My e dovremmo istanziare noi un oggetto della classe Network per ottenere lo stesso effetto.

Inoltre, l'elenco dei membri che appare grazie all'IntelliSense in VB .NET è diviso in due schede in cui vengono messi in evidenza gli elementi di uso comune, facilitando la selezione della voce desiderata. In C# l'elenco dei membri viene sempre visualizzato nella sua interezza.

Figura 1: L'IntelliSense di Visual Basic .NET

2a.gif

Questa rapida carrellata sulle differenze tra C# e Visual Basic .NET non ha la pretesa di essere esaustiva: per maggiori informazioni (riguardanti soprattutto le più evidenti diversità di sintassi), consultare i collegamenti a fine pagina. Inoltre, disponendo di Visual Studio 2005, è possibile ottenere maggiori dettagli sull'argomento cercando Language Equivalents nella guida in linea.

Il primo programma​
Il .NET framework SDK, ovvero l'insieme di tutti gli strumenti necessari alla creazione di software per la piattaforma .NET, è liberamente
Perfavore, Entra oppure Registrati per vedere i Link!
dal sito Microsoft.

Dunque è sufficiente usare un editor di testi per sviluppare applicazioni .NET, anche se quando ci si orientasse verso programmi più complessi e dotati di interfaccia grafica, l'adozione di un ambiente di sviluppo visuale diventa quasi indispensabile.

Realizziamo subito il nostro primo programma. Costruiremo un'applicazione "console", ovvero eseguibile dal prompt dei comandi.

Per scrivere un programma di questo tipo non è strettamente necessario un ambiente di sviluppo come Visual Studio (che analizzeremo in dettaglio nelle prossime Lezioni), data l'assenza di elementi grafici o di connessioni complesse tra classi.

Pensiamo di voler realizzare la classica applicazione che stampa a video la stringa "Ciao Mondo!", aspetta che l'utente prema il tasto INVIO e, quindi, termina. Il codice è il seguente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Chi ha già una conoscenza di Java potrà notare una certa somiglianza, dal punto di vista della sintassi, tra i due linguaggi. Per eseguire il programma, salviamolo in un file di testo con nome, ad esempio, HelloWorld.cs. Lìestensione «.cs» contraddistingue i file sorgenti di C#.

Con la versione 2.0 di .NET, nel menù Start di Windows comparirà il gruppo Microsoft .NET Framework SDK v2.0, al cui interno si trova il comando SDK Command Prompt che permette di aprire un prompt dei comandi con le variabili di sistema per l'uso degli strumenti a riga di comando del Framework già impostate.

Quindi possiamo spostarci nella cartella in cui è stato salvato il file «Hello.cs» e digitare il comando:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
csc.exe è il compilatore C#, il risultato di questa operazione è un file eseguibile di nome «Hello.exe». Per avviare il frutto delle nostre fatiche è sufficiente digitare:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Iniziamo a prendere dimestichezza con la struttura di un programma C# esaminando le poche righe di questo esempio.

L'espressione «public class HelloWorld» serve per definire una classe di nome «HelloWorld». Quello di classe è un concetto fondamentale, che approfondiremo nel corso delle prossime lezioni, al momento basti sapere che tutto il codice di un programma C# definisce classi e scambi di informazioni tra classi.

main è un metodo particolare. Il cosiddetto punto di ingresso dell'applicazione, ovvero il primo metodo che viene richiamato quando si avvia il programma.

Tutti i programmi eseguibili realizzati con C#, compresi quelli per Windows, devono avere una (e solo una) classe con all'interno un metodo main, altrimenti in fase di esecuzione si otterrà un messaggio di errore.

L'istruzione System.Console.WriteLine() stampa a video il messaggio, mentre System.Console.ReadLine() fa sì che l'applicazione aspetti che l'utente prema il tasto INVIO prima di terminare.

Abbiamo così realizzato un semplice programma in C#, per prendere subito confidenza con i primi strumenti e per stimolare la nostra curiosità su alcuni concetti che saranno trattati con maggior dettaglio nelle prossime lezioni.

L'esempio che abbiamo costruito può essere scaricato
Perfavore, Entra oppure Registrati per vedere i Link!


Le Classi​
Il concetto di classe è alla base di ogni linguaggio di programmazione orientato agli oggetti ed ha la potenza di definire le caratteristiche di un insieme di oggetti che hanno proprietà e compiono azioni uguali. Rappresenta tutti gli oggetti che appartengono ad una certa classe, appunto.

Per fare un'esempio si pensi alle automobili: ogni automobile è diversa da un'altra ma tutte hanno quattro ruote un propulsore e compiono l'azione di avanzare o frenare. Questi elementi comuni le fanno rientrare in un unico concetto. Un'unica classe.

Più praticamente una classe è una collezione di variabili, metodi e proprietà. Anche in questo caso, C# riprende la sintassi di Java dove per definire una classe si usa il costrutto class.
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Una classe è identificata anche come "tipo di dato", infatti porta con se sia la rappresentazione dei dati, sia le operazioni sugli stessi, in realtà il concetto di classe è più vasto.

Possiamo però cosiderare le istanze di una classe, ovvero gli oggetti che realizzano il concetto di classe, come variabili definite da un certo tipo di dato.
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Per ogni classe istanziata, viene creato un'oggetto ed è invocato un metodo detto costruttore della classe. Il costruttore, così come avviene in Java e in C++, ha lo stesso nome della classe e non restituisce alcun valore (nel nostro esempio il metodo public Persona). In VB .NET, invece, il costruttore è definito in un metodo dichiarato come Sub New.

Il costruttore è utilizzato per impostare le proprietà che la classe deve avere al momento della sua creazione: nel nostro esempio, quando si crea una istanza della classe Persona, le sue variabili mNome e mCognome assumono i valori specificati nel relativo argomento del costruttore.

Dichiarazione dei metodi

I metodi di una classe possono essere definiti come public, private, protected oppure internal (Friend in Visual Basic .NET): queste parole chiave vengono solitamente chiamate modificatori di accesso.

Con public, una routine diventa accessibile da tutte le istanze della classe. Private, invece, impedisce che la routine sia visibile al di fuori della classe di in cui è definita.

Se non si specifica il modificatore di accesso, private è il valore predefinito. Ad esempio, utilizzando ancora la nostra classe Persona:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Dichiarando una metodo della classe Persona come protected, essa sarà visibile nell'ambito in cui definiamo le classi che ereditano da Persona ma non potrà essere utilizzata nel codice in cui istanziamo oggetti di questa classe. L'ereditarietà sarà trattata nelle prossime lezioni.

In pratica, protected equivale a private, con la differenza che il metodo è visibile anche alle classi che ereditano da quella principale. Infine, ciò che è dichiarato come internal è visibile solo all'interno dell'assembly dell'applicazione; per il concetto di assembly fare riferimento alle Lezioni dedicate all'uso di Visual Studio 2005.

Dopo il modificatore di accesso del metodo, nella dichiarazione è necessario specificare il tipo di dato restituito.

È possibile indicare un qualsiasi tipo di dato: int, string, byte, etc. Si può specificare anche il nome di una classe, poiché, ricordiamo, una classe è un tipo. Questo tipo di metodi corrisponde alle Function di VB.

Per restituire il valore, è necessario utilizzare la parola chiave return, seguita da una qualsiasi espressione che abbia lo stesso tipo del valore di ritorno del metodo. Tale istruzione causa anche l'uscita dal metodo. Ad esempio:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
In C# un metodo che restituisce un valore deve obbligatoriamente contenere la parola chiave return, altrimenti, in fase di compilazione, si otterrà un errore.

Le funzioni di Visual Basic, invece, possono non presentare il return: in tal caso il valore restituito è quello di default per il particolare tipo di dati.

I metodi che non restituiscono un valore, come StampaMessaggio() e Appoggio() dell'esempio, hanno tipo void; essi corrispondono alle Sub di Visual Basic. Si può comunque usare la parola return in un metodo void, che in questo caso ha il solo scopo di uscire dalla procedura: in questo caso, quindi return non deve essere seguito da alcuna espressione.

Le proprietà
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Essa permette di avere accesso in lettura/scrittura alla variabile mNome, che altrimenti non sarebbe visibile all'esterno della classe. Il blocco get deve restituire la variabile associata alla proprietà, quindi, come detto prima, deve contenere l'istruzione return.

Il codice del blocco set, invece, viene eseguito quando si modifica il valore della proprietà; la parola chiave value contiene il nuovo valore da assegnare. L'utilizzo delle proprietà è intuitivo:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Allo stesso modo è possibile aggiungere una proprietà Cognome.

È lecito domandarsi perché utilizzare le proprietà, quando si potrebbe più semplicemente rendere pubbliche le variabili mNome e mCognome. Conviene avere una classe con membri privati accessibili solo tramite proprietà quando si devono effettuare dei controlli sui valori assegnati ai membri stessi.

Ad esempio, supponiamo di voler impedire che l'utente inserisca un nome o un cognome vuoto: se impostiamo le variabili mNome e mCognome come pubbliche questo controllo non può essere effettuato.

Infatti si ha libero accesso alle variabili che possono essere impostate su qualunque stringa valida (compresa, dunque, la stringa vuota). Per risolvere il problema, è sufficiente definire i membri come privati e modificare la proprietà Nome nel modo seguente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
In modo analogo, anche la proprietà Cognome deve essere ridefinita.

string.Empty è un campo a sola lettura che rappresenta la stringa vuota. Se Nome oppure Cognome vengono impostati sulla stringa vuota, questo codice li definisce, rispettivamente, come Nessun nome e Nessun cognome.

Notiamo che, per ottenere un comportamento coerente di tutta la classe, anche il costruttore deve essere modificato in modo da effettuare un controllo sugli argomenti.

È buona norma definire delle proprietà che consentano di modificare i valori delle variabili utilizzate da una classe, in modo da avere un maggior controllo sui dati specificati, piuttosto che dare libero accesso alle variabili stesse.

Le proprietà possono anche essere di sola lettura, se dispongono del solo blocco get, oppure di sola scrittura, se hanno solo il codice associato al set.

Per ottenere un comportamento analogo in Java oppure in C++, è necessario definire due metodi distinti, i cosiddetti metodi getter (per recuperare il valore) e setter (per impostarlo).

Il codice completo della classe può essere scaricato qui. Nel file da scaricare è incluso un semplicissimo esempio di uso della classe Persona.


Metodi «statici»
Negli esempi visti finora, per accedere ai metodi della classe Persona occorreva creare un'istanza della classe. In alcuni casi, tuttavia, può risultare utile avere delle procedure che non hanno bisogno di un'istanza per essere utilizzate, ma che possono essere richiamate semplicemente con il nome della classe.

Ad esempio, supponiamo che il metodo Quadrato di cui abbiamo parlato in precedenza sia contenuto nella classe «Matematica». È sensato pensare che una procedura di questo tipo possa essere richiamata senza dover prima creare un'istanza della classe che la contiene. Per questo si usa la parola chiave static (che corrisponde allo Shared di VB .NET):
Una classe può contenere anche un altro tipo di metodi, le cosiddette proprietà. Si tratta di particolari routine che permettano di leggere e/o impostare i valori di determinate proprietà di una classe. Aggiungiamo, per esempio, la seguente proprietà alla classe Persona:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
L'utilizzo di questa routine è immediato:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Notiamo che le funzioni WriteLine() e ReadLine() della classe Console, che abbiamo introdotto in precedenza, sono proprio metodi statici.


I namespace

Più classi possono essere raggruppate in un unico namespace. Ad esempio:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Con questo costrutto, per dichiarare, ad esempio, un oggetto di tipo Classe1 è necessario scrivere:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
lo stesso vale per Classe2. Fatto questo, è possibile accedere ai metodi ed alle proprietà delle classi nel modo consueto. I namespace sono sempre public.
È possibile definire namespace annidati, ad esempio:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Tutte le classi che compongono l'infrastruttura .NET sono organizzate in namespace. Ad esempio, la classe Form, da cui ereditano tutte le Windows form (che tratteremo in seguito) è raggiungibile nel namespace Windows.System.Forms.Form.

Per non dover indicare ogni volta i namespace in cui si trovano le classi che si stanno utilizzando, è possibile utilizzare la parola chiave using (analoga a import di Java), con cui si specifica in quali namespace devono essere cercate le classi.

Le clausole using devono essere specificate all'inizio della classe, prima di qualunque altra istruzione. Ad esempio, nel programma «HelloWorld» realizzato nelle precedenti lezioni si fa uso della classe Console, che è contenuta nel namespace System; invece di indicarlo esplicitamente, è possibile ricorrere alla parola chiave using:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Fare clic
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare il codice sorgente della classe Matematica, compreso un esempio del suo utilizzo.

I tipi di dati base e passaggio dei parametri​
I tipi di dati base derivano direttamente dai tipi di dato di Java, dei quali conservano anche il nome, anche la conversione tra tipi di dato, il cosiddetto «casting» funziona alla maniera di Java. Ci sono invece novità introdotte da C# per quanto riguarda i tipi di dato definiti dall'utente: le struct e le enum.

Il tipo struct permette di definire nuovi tipi di dati a partire da quelli esistenti:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Questa dichiarazione definisce un tipo di dato Persona composto da due variabili di tipo stringa (i cosiddetti membri della struttura). Notiamo che, a differenza del C++, da cui deriva il concetto di struct, ogni membro deve avere un modificatore di accesso (public, private, ecc.).

Questo perché il tipo struct è molto potente: può essere dotato di un costruttore (che si comporta esattamente come il costruttore di una classe), di proprietà e di metodi. Modifichiamo la struttura Persona aggiungendovi un costruttore e una proprietà che restituisce il nome completo, quindi riprendiamo il nostro primo programma ed aggiorniamolo per mostrare l'uso della struct:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
All'interno del metodo Main la struttura Persona viene utilizzata come se si trattasse di una classe. Notiamo che, invece di usare il costruttore, avremmo potuto scrivere:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Ottenendo lo stesso risultato, ovvero la stampa del messaggio "Ciao Marco Minerva!". Questo è possibile perché i membri Nome e Cognome della struttura sono stati dichiarati public; se, invece, fossero stati definiti private, non sarebbe stato consentito utilizzare le tre istruzioni sopra riportate (si sarebbe ottenuto un errore in fase di compilazione, come già spiegato a proposito delle classi), e l'unico modo lecito di impostare i membri Nome e Cognome sarebbe stato quello di utilizzare il costruttore.

Fare clic qui per scaricare l'esempio.
A questo punto è naturale chiedersi quali siano le differenze tra struct e class. La spiegazione è fornita dalla guida in linea: "Il tipo struct è adatto alla rappresentazione di oggetti leggeri [...] Se ad esempio si dichiara una matrice di 1.000 oggetti [classi] Point, si allocherà ulteriore memoria per i riferimenti a ciascun oggetto. In questo caso la struttura risulta meno onerosa". Inoltre una struct può implementare interfacce ma non può ereditare.

Le enum consentono di associare nomi simbolici a costanti numeriche. Il costrutto deriva dal C++ dove i membri delle enum sono sempre di tipo «int», mentre in C# è possibile indicarne esplicitamente il tipo:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Questa dichiarazione definisce una enumerazione i cui membri sono di tipo byte. Richiamando il metodo ToString() di una variabile di tipo enum, è possibile ottenere la stringa contenente il nome simbolico del valore corrente. Ad esempio:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Questo codice stampa a video il messaggio "Stato selezionato: America".

Concludiamo questa Lezione con qualche cenno sul passaggio dei parametri ai metodi. I parametri in C# possono essere passati in tre modi: in, out e ref.

Queste parole chiave determinano cosa accade alla variabile passata come argomento quando si esce dal metodo.

in è il tipo di passaggio predefinito: la routine non può modificare la variabile, o, meglio, qualunque modifica della variabile interna al metodo viene persa quando si esce dal suo scope (il tipico passaggio "per valore").
ref e out sono i classici passaggi di parametro per riferimento. Viene passato il riferimento (il puntatore) alla variabile e non il suo valore, così anche nello scope del metodo si fa riferimento allo stasso oggetto in memoria.
La differenza tra ref e out è che ref richiede che si inizializzi la variabile prima della chiamata del metodo, mentre con out è sufficiente dichiarare la variabile e passarla senza inizializzazione. In pratica con out è possibile inizializzare intere strutture dati dall'interno di un metodo.
Vediamo ora alcuni semplici esempi per chiarire quanto illustrato:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Un possibile utilizzo di questi metodi è il seguente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Osserviamo che, per utilizzare un parametro out oppure ref nella chiamata ad un metodo, è necessario indicare esplicitamente che si tratta di un argomento passato out o ref.

Ereditarietà​
L'ereditarietà è uno dei concetti base della programmazione orientata agli oggetti. Si definisce ereditarietà la possibilità per una classe (detta classe derivata) di ereditare da un'altra (la classe base) le variabili, i metodi, le proprietà e di estendere il concetto della classe base e specializzarlo.

Tornando all'esempio delle automobili potremmo avere come classi derivate da automobili le sottoclassi: «auto con cambio manuale» e «auto con cambio automatico». Entrambe le sottoclassi ereditano tutte le proprietà e i comportamenti della classe base ma specializzano il modo di cambiare le marce.

Tutte le classi del Framework .NET ereditano implicitamente dalla classe base Object. In C# la relazione di ereditarietà tra le classi si esprime usando i due punti (:emoji_slight_smile: che equivalgono a Inherits di VB.NET .

Riprendiamo una parte della classe Persona che abbiamo realizzato in precedenza:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Osserviamo che la variabile mCognome è stata dichiarata come protected. Vogliamo ora definire un nuovo concetto, quello di Studente, ovvero una Persona dotata di un numero di matricola. Per fare questo, Studente deve ereditare da Persona (si può dire anche che Studente estende Persona):
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Avendo definito questa relazione, nella classe Studente è possibile utilizzare tutto ciò che in Persona è stato definito come public, protected o internal, sia esso una variabile, una routine o una proprietà.

Ad esempio, all'interno di Studente è possibile utilizzare la variabile mCognome, che in Persona è definita protected, mentre mNome non è visibile, poiché il modificatore di accesso predefinito è private.

Esaminiamo il frammento
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
subito dopo il costruttore di Studente. Esso richiama il costruttore della classe base passandogli gli argomenti specificati: in questo modo è possibile impostare le variabili mNome e mCognome della classe Persona sugli stessi valori passati al costruttore di Studente.

Se avessimo voluto che il nome della persona, indipendentemente da quanto indicato nel costruttore di Studente, fosse sempre "Pippo", mentre il cognome fosse quello passato, sarebbe stato sufficiente scrivere:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Questo costrutto è necessario perché, quando si crea un oggetto di una classe che deriva da un'altra, prima del costruttore della classe derivata viene richiamato quello della classe base: nel nostro esempio, quando si istanzia un oggetto di tipo Studente, viene richiamato prima il costruttore della classe Persona, e, in seguito, quello di Studente.

Poiché la classe Persona non ha un costruttore senza argomenti, bisogna indicare esplicitamente tramite la parola chiave «base» quale costruttore richiamare. Se invece Persona avesse avuto un costruttore privo di argomenti, «base» non sarebbe servita.

Oltre che a questo scopo, «base» serve, in generale, per avere accesso ai metodi, alle variabili ed alle proprietà della classe che si sta derivando. Il corrispondente di «base» in Visual Basic è la parola chiave MyBase.

Provando a dichiarare oggetti di tipo Persona e Studente, si ottiene quanto segue:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Senza le istruzioni : Persona e : base(Nome, Cognome) nella classe Studente, eliminiremmo l'ereditarietà e otterremmo un messaggio di errore relativo all'istruzione:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare le due classi Persona e Studente.

Grazie all'ereditarietà, dove è previsto l'uso di una certa classe, è quasi sempre possibile utilizzare una classe derivata. Questo è, probabilmente, uno degli aspetti più interessanti dell'ereditarietà.

Per esempio, supponiamo di avere una funzione che, ricevuti come argomenti due oggetti di tipo Persona, restituisce true se i loro nomi sono uguali:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Come argomenti a questa funzione, possono essere passati sia istanze della classe Persona, sia istanze di tutte le classi che ereditano da Persona, quindi anche oggetti di tipo Studente. Infatti, dal momento che esso eredita da Persona, dispone di tutte le proprietà pubbliche della classe base (in altre parole, uno Studente è una Persona, quindi può essere usato in tutti i contesti in cui è richiesta una Persona). Il seguente codice è corretto:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Un fatto molto interessante è che all'interno della routine NomiUguali la variabile stud viene vista come una Persona, e, quindi, di stud sono visibili i metodi e le proprietà pubbliche della classe Persona, non quelli di Studente.

È possibile scaricare un esempio di utilizzo cliccando
Perfavore, Entra oppure Registrati per vedere i Link!


L'ereditarietà è singola, in C# come in VB.NET, ovvero una classe può avere solo una classe base, a differenza del C++, che supporta l'ereditarietà multipla: in altre parole, non è possibile definire una classe C che eredita contemporaneamente da A e da B. Torneremo su questi concetti più avanti.

Polimorfismo​
Il termine polimorfismo indica la possibilità di definire metodi e proprietà con lo stesso nome, in modo che, ad esempio, una classe derivata possa ridefinire un metodo della classe base con lo stesso nome.

Continuiamo ad usare le nostre classi Persona e Studente realizzate nelle lezione precedente per capire il concetto di polimorfismo. Inizialmente, avevamo definito il metodo pubblico StampaMessaggio() nella classe Persona, ma non ne abbiamo ancora scritto il corpo. Vogliamo fare in modo che questa routine stampi a video le informazioni sulla persona.

È naturale pensare che, analogamente, anche la classe Studente abbia un metodo StampaMessaggio() che mostri, oltre alle informazioni sulla persona, anche quelle proprie di uno studente. Perciò dobbiamo definire i metodi nel modo seguente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il metodo StampaMessaggio() è definito in entrambe le classi, ma ha un comportamento diverso, dal momento che in Studente viene stampato anche il numero di matricola.

A seconda che si dichiari un oggetto di tipo Persona oppure Studente, verrà richiamata la routine StampaMessaggio() corrispondente. Per fare questo, abbiamo usato il polimorfismo: il metodo StampaMessaggio() nella classe base è stato dichiarato usando la parola chiave «virtual» (che corrisponde a Overridable in Visual Basic .NET): con essa si indica che è possibile avere un'altra definizione per la stessa routine in una classe derivata.

In Studente, infatti, StampaMessaggio() è stato definito specificando la parola chiave «override» (Overrides in VB): in questo modo si dice che tale funzione sovrascrive un metodo con lo stesso nome che è stato definito nella classe base.

In alcuni casi può essere necessario, all'interno del metodo ridefinito, richiamare il metodo che si sta ridefinendo. Nel nostro esempio, il metodo StampaMessaggio() della classe Studente potrebbe richiamare il metodo StampaMessaggio() di Persona, che si occupa già di mostrare il nome e il cognome, limitandosi quindi a stampare solo le informazioni proprie di uno studente.

Per fare questo, si deve usare la parola chiave «base», che, come già accennato nella lezione precedente, consente di avere accesso alla classe che si sta derivando; alla luce di queste considerazioni, il metodo StampaMessaggio() di Studente diventa:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
In pratica, base.StampaMessaggio() richiama il metodo corrispondente nella classe base.

L'esempio che abbiamo realizzato può essere scaricato cliccando qui.

C'è anche un altro modo per sfruttare il polimorfismo, ovvero usando la parola chiave «new» (equivalente a Shadows in VB .NET), che nasconde una definizione della classe base con lo stesso nome. L'esempio sopra riportato, usando «new», diventa:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Come si vede, nella classe base la parola chiave «virtual» è sparita, mentre in Studente il metodo StampaMessaggio() è preceduto da «new».

È possibile scaricare le due classi modificate cliccando
Perfavore, Entra oppure Registrati per vedere i Link!


È importante notare che, usando la coppia «virtual» e «override», il metodo che sovrascrive una routine della classe base deve avere non solo lo stesso nome, ma anche lo stesso numero di argomenti e dello stesso tipo.

Invece, usando «new», è possibile ridefinire un metodo completatmente. Con «new» si può addirittura nascondere una variabile della classe base con un intero metodo nella classe derivata.

Questa rapida panoramica è solo una introduzione al polimorfismo, per approfondire è sempre utile consultare la Guida in linea.

Overloading​
Overloading significa «sovraccaricare» ovvero definire più versioni di un metodo, utilizzando lo stesso nome ma una firma diversa.

Per firma di un metodo si intede il numero e/o il tipo di argomenti nella dichiarazione. Sulla base degli argomenti effettivamente passati alla routine, verrà riconosciuta la firma e richiamato il metodo corretto.

Vediamo subito un esempio:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Le due definizioni della routine Stampa() differiscono solo per il tipo dell'argomento: string nel primo caso, int nel secondo. Richiamando questi due metodi, si ottiene il seguente risultato:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
L'overloading viene spesso usato nella definizione del costruttore di una classe. Riprendiamo il costruttore della nostra classe Persona:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Finora, per creare una persona senza nome né cognome, era necessario passare esplicitamente la stringa vuota nel costruttore:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
In questo caso, però, sarebbe preferibile poter istanziare la classe Persona senza passare alcun argomento al costruttore. Tale risultato può essere facilmente raggiunto con l'overloading del costruttore:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Così facendo, se si crea una Persona indicando nome e cognome, essi verranno salvati nelle variabili mNome e mCognome, poiché viene richiamato il costruttore Persona(string Nome, string Cognome), mentre, se si crea una Persona senza parametri, è invocato il costruttore Persona(), che imposta mNome e mCognome, rispettivamente, su "Nessun nome" e "Nessun cognome".
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Un costruttore può chiamarne un altro. Nel nostro esempio, anziché assegnare esplicitamente le variabili mNome e mCognome nel costruttore senza argomenti, sarebbe stato possibile richiamare l'altro costruttore, "dicendogli" come impostare il nome e il cognome della persona:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
La parola chiave «this» permette di avere accesso ai metodi, alle variabili ed alle proprietà della classe corrente, così come «base» permette di avere accesso alla classe da cui si eredita. Il corrispettivo di «this» in VB.NET è «Me».

Questa soluzione è da preferire poiché, in caso di modifiche al costruttore, è sufficiente intervenire su un solo punto del codice.

Se, ad esempio, dopo aver creato la classe Persona, si decidesse che il nome deve essere sempre preceduto dalla stringa "Sig.", nel primo esempio di overloading del costruttore sarebbe stato necessario modificare il codice in due parti diverse.

Nel caso in cui siano previsti più costruttori, le porzioni di codice da cambiare possono essere più numerose e, quindi, aumenta la probabilità di dimenticarsi qualche modifica.

La nuova classe Persona è disponibile
Perfavore, Entra oppure Registrati per vedere i Link!


Overloading degli operatori

L'overloading degli operatori, derivato dal C++, consiste nel ridefinire il comportamento di operatori come +, - , <, >, ==, etc., affinchè assumano comportamenti a seconda degli oggetti cui sono applicati.

C# supporta l'overloading degli operatori a partire dalla sua prima versione, mentre VB.NET ha introdotto questa funzionalità solo con la versione 2.0 del Framework.

Partiamo come sempre dalla classe Persona. Non avendo altre informazioni, C# assume che due variabili di tipo Persona siano uguali se fanno riferimento all'istanza dello stesso oggetto, ovvero:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Quello che vorremmo, invece, è che due persone risultassero uguali se il nome e il cognome fossero gli stessi (nell'esempio sopra riportato, vorremmo che il primo confronto 'p1 == p2' restituisse true).

Per fare questo, o ogni volta facciamo il controllo sulle proprietà Nome e Cognome oppure, più semplicemente, ridefiniamo l'operatore '==' per la classe Persona creando un metodo con la parola chiave «operator»:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Bisogna ridefinire insieme gli operartori che stabiliscono relazioni simili. Avendo ridefinito l'operatore '==', il Framework ci richiede che venga ridefinito anche l'operatore '!=' (e viceversa), così come, se avessimo ridefinito <, avremmo dovuto definire anche > (e viceversa).

L'overloading degli operatori è sempre definito con metodi statici. Dopo l'indicazione del tipo di dato restituito (solitamente bool oppure lo stesso tipo della classe per cui si sta creando l'overloading, a seconda dell'operatore in questione), è necessario specificare l'operatore che si sta ridefinendo.

Sulla guida in linea troviamo l'elenco di tutti gli operatori che possono essere sottoposti ad overloading.

Infine, bisogna indicare a quali tipi di dati si applica: nel nostro esempio, '==' e '!=' si applicano a oggetti della classe Persona.

Gli argomenti del metodo sono due nel caso di operatori binari (come mostrato nel nostro esempio), oppure uno solo se l'operatatore è unario (++, --, ecc.).

Ridefinendo gli operatori '==' e '!=', il compilatore si aspetta che vengano anche ridefiniti i metodi Equals() e GetHashCode(), che ogni classe possiede in quanto li eredita dalla classe base Object. Ad ogni modo, se non vengono specificati, si ottiene solo un warning di compilazione. Definiamoli comunque, per avere una classe più robusta:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Nel metodo Equals() si è utilizzato l'operatore «is», necessario per controllare che l'oggetto passato alla funzione sia di tipo Persona: in caso positivo, l'oggetto viene convertito e il controllo sull'uguaglianza è fatto utilizzando la nostra definizione di '=='.

Altrimenti, l'oggetto corrente viene convertito ad Object, quindi si usa il confronto standard, per cui due variabili di tipo object sono uguali se fanno riferimento all'istanza dello stesso oggetto.

Grazie a questa ridefinizione, ora possiamo ottenere il risultato desiderato:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare la classe Persona realizzata fino a questo punto.

A titolo di esempio, nel file da scaricare è stato ridefinito anche l'operatore '+', che "somma" due persone, ovvero crea una nuova Persona il cui nome e cognome sono la concatenazione dei nomi e dei cognomi delle persone di partenza. Al di là dell'utilità di un'operazione del genere, si tratta comunque di un esempio in più da tenere in considerazione.

Le classi astratte​
Una classe astratta è un tipo particolare di classe di cui non si può creare una istanza con la parola chiave «new». Per essere utilizzata, infatti, deve essere obbligatoriamente ereditata. Mostriamo subito un esempio di classe astratta, partendo dal quale introdurremo una serie di importanti concetti:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Una classe astratta si dichiara con la parola chiave «abstract». Al suo interno possono essere definite variabili, metodi e proprietà, proprio come abbiamo fatto finora (nell'esempio sopra riportato, le variabili mNome e mNumeroLati, il costruttore, e le proprietà Nome e NumeroLati).

Oltre a ciò, è possibile dichiarare un'altra serie di metodi e proprietà che devono essere obbligatoriamente implementate dalle classi che ereditano da essa: i cosiddetti metodi e proprietà astratti.

Nel nostro caso, la classe che eredita da Figura deve fornire una implementazione delle proprietà Perimetro e Area (dalla definizione si comprende che saranno di sola lettura, se fossero state di lettura/scrittura avremmo avuto get; set;) e del metodo Disegna.

La classe Quadrato eredita correttamente da Figura:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Figura è la classe che racchiude le caratteristiche comuni ad ogni figura geometrica. La definizione fornita obbliga tutte le classi che ereditano da essa a ridefinire i metodi e le proprietà dichiarati abstract, altrimenti in fase di compilazione si otterrà un messaggio di errore in quanto alla dichiarazione del metodo non corrisponde nessuna azione concreta: nessun codice da eseguire.

Ad esempio, eliminando il metodo Disegna dalla classe Quadrato, la compilazione fallisce segnalando che 'Quadrato' non implementa il metodo astratto ereditato Figura.Disegna().

Per le classi astratte valgono le stesse considerazioni fatte a proposito dell'ereditarietà, ovvero se un metodo richiede una classe astratta come argomento, al suo posto potrà essere utilizzata una qualunque classe che eredita da essa.

In VB.NET una classe astratta si dichiara con MustInherit e un metodo astratto con MustOverride.

Fare clic
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare l'esempio che abbiamo realizzato; nel file ZIP è disponibile anche la classe triangolo.

Le interfacce​
A differenza delle classi astratte, un'interfaccia è un gruppo completamente astratto di membri che può essere considerato come la definizione di un contratto: chi implementa una interfaccia si impegna a scrivere il codice per ciascun metodo.

Questo significa, in primo luogo, che tutti i metodi e le proprietà definite all'interno di un'interfaccia sono implicitamente astratti, ovvero non è possibile fornirne l'implementazione all'interno dell'interfaccia stessa. Per creare un'interfaccia, si utilizza la parola chiave «interface»:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
In questo esempio abbiamo seguito la convenzione secondo cui i nomi delle interfacce dovrebbe iniziare con la lettera I maiuscola. Tutto ciò che è dichiarato all'interno di una interfaccia è pubblico (ed è un errore indicare il modificatore public).

Un'interfaccia non può contenere variabili, struct, enum e, come già accennato, implementazioni di metodi (tutte cose che, invece, sono consentite nelle classi astratte).

Un'interfaccia viene implementata da una classe. Per indicare che una classe implementa un'interfaccia, in C# si usa il carattere ":", lo stesso con cui si esprime l'ereditarietà tra classi (in VB.NET si usa la parola chiave Implements):
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Come avviene per le classi astratte, la classe che implementa un'interfaccia deve fornire l'implementazione di tutti i suoi metodi e delle sue proprietà, in questo caso però non c'è bisogno della parola chiave override, è sufficiente che i metodi definiti abbiano lo stesso nome con cui sono dichiarati nell'interfaccia.

In VB.NET, invece, i nomi assegnati ai metodi non sono vincolanti, poiché il metodo dell'interfaccia che si sta implementando è indicato esplicitamente.

Come già visto in precedenza, una classe può ereditare da una sola classe base, mentre può implementare un numero illimitato di interfacce: in questo caso, è necessario definire i metodi e le proprietà di tutte le interfacce:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Questa dichiarazione indica che la classe Studente estende Persona e implementa IEsempio1 ed IEsempio2.

Supponiamo che IEsempio1 ed IEsempio2 contengano un metodo con lo stesso nome, ad esempio un metodo void Calcola(). La classe Studente deve definirli entrambi: per evitare conflitti, i nomi dei metodi devono essere preceduti dal nome dall'interfaccia in cui sono definiti:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Un'interfaccia può ereditarne un'altra: in questo caso, la classe che implementa l'interfaccia ereditata deve implementare non solo tutti i suoi metodi e proprietà, ma anche quelli dell'interfaccia base.

Un oggetto che implementa un'interfaccia, inoltre, può essere utilizzato in tutte le parti del codice in cui è richiesta tale interfaccia, quindi anche le interfacce definiscono una nozione di ereditarietà.

Sia le interfacce sia le classi astratte servono per definire una serie di funzionalità di base che devono essere realizzate dalle classi che le ereditano o le implementano.

La scelta di utilizzare un'interfaccia oppure una classe astratta può a volte risultare difficile. MSDN consiglia:

«Mediante le classi astratte possono essere forniti anche membri che sono già stati implementati. Pertanto, con una classe astratta è possibile garantire una certa quantità di funzionalità identiche, a differenza di quanto avviene con un'interfaccia (che non può contenere alcuna implementazione)[...].

Se le funzionalità da creare saranno utilizzate in una vasta gamma di oggetti diversi, usare un'interfaccia. Le classi astratte devono essere usate principalmente per gli oggetti strettamente correlati, mentre le interfacce sono più adatte a fornire funzionalità comuni a classi non correlate».

Visual Studio 2005​
Gli esempi che abbiamo realizzato finora erano di una semplicità tale da poter essere scritti con un comune editor di testi. Tuttavia, nel momento in cui ci si orienta verso applicazioni più complesse, soprattutto se dotate di interfaccia grafica, è consigliabile utilizzare un ambiente di sviluppo visuale.

Lo strumento "principe" per la realizzazione di applicazioni che si basano sul Framework .NET è Visual Studio. Alla sua ultima versione 2005 (in fase di beta testing al momento della stesura di questa guida), questo ambiente di sviluppo migliora sensibilmente le caratteristiche di usabilità e potenza che lo hanno da sempre contraddistinto.

Figura 1: L'ambiente di sviluppo Visual Studio 2005
12a.gif

L'interfaccia di Visual Studio 2005 dovrebbe risultare familiare a chi ne ha già utilizzata una versione precedente. Alcuni riferimenti possiamo trovarli a fine pagina.

La procedura per creare una applicazione Windows è simile alla precendete versione anche se la finestra di dialogo Nuovo Progetto (New Project) è cambiata, come visibile in figura.

Figura 2: La nuova finestra di dialogo New Project
12b.gif

Le novità introdotte dalla nuova release di Visual Studio, relativamente al miglioramento della produttività, possono essere riassunte in cinque concetti essenziali:

Smart Tag: Visual Studio 2005 supporta un discreto numero di Smart Tag per velocizzare le operazioni più comuni;
IntelliSense: ora il completamento automatico del codice si attiva non appena si inizia a digitare qualcosa nell'editor. È attivo anche durante la scrittura di pagine ASP .NET
Refactoring: con questo termine si intende una serie di funzionalità che permettono di modificare velocemente e sistematicamente il codice scritto.
tra le altre caratteristiche, cambiando il nome di una variabile, di un metodo o di una proprietà, uno Smart Tag consente di rinominare automaticamente tutte le occorrenze della stringa modificata.

Figura 3: Il refactoring di Visual Studio 2005 in azione
12c.gif

Code Snippets e Surrounding: gli "snippet" sono porzioni di codice di uso comune, come il codice dei costrutti for e while, che possono essere inseriti facendo clic col tasto destro del mouse nella finestra del codice e selezionando il comando Insert Snippet..., oppure, più semplicemente, digitando il nome dello snippet e premendo due volte il tasto TAB.
Queste porzioni di codice possono contenere dei parametri. In tal caso, dopo l'inserimento, il cursore si posiziona automaticamente sul primo di essi: per spostarsi tra i parametri, si usa il tasto TAB.

Il Surrounding, invece, è letteralmente la possibilità di "circondare" un blocco di istruzioni con un certo costrutto, ad esempio for oppure try...catch...finally

Figura 4: Inserimento di uno snippet di codice

12d.gif

Finestra dei task comuni: selezionando un controllo in una Windows Form, in alto a destra viene visualizzata un piccolo riquadro con una freccia verso destra: facendo clic su di esso, compare una finestra che consente di impostare velocemente le proprietà usate più di frequente per l'oggetto in questione.
Altra novità interessante, forse una delle più richieste, è la funzionalità di Edit & Continue, che deriva dalle vecchie versioni di Visual Basic e che finalmente è supportata anche da C#.

Consiste nella possibilità di modificare il codice durante il debug del programma senza interromperne l'esecuzione (ovviamente a patto di non alterare il flusso delle istruzioni).

Ci sono miglioramenti volti a rendere ancora più semplice il debugging delle applicazioni e il Class Designer (Progettazione Classi), per costruire in modo grafico lo schema delle classi, usando un approccio in stile UML.

Windows Form​
La Windows Form, ovvero la finestra dell'applicazione, è il fulcro di ogni applicazione Windows. La versione 2.0 del framework .NET introduce parecchie novità nella gestione delle Windows Form, che cercheremo di analizzare nel seguito.

Creiamo una nuova Windows Application (applicazione Windows) con il linguaggio C#, come indicato nella lezione precedente. Il progetto include di default una Windows Form, contenuta in un file di nome Form1.cs.

Premiamo il tasto F7 per visualizzare il codice sorgente; in alternativa, è possibile fare clic con il tasto destro del mouse sul file «Form1.cs» visualizzato nel Solution Explorer (Esplora soluzioni) e selezionare il comando View code (Visualizza codice). Viene mostrato il codice:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Innanzi tutto, notiamo varie clausole using che specificano quali sono i namespace in cui cercare le classi che verranno utilizzate.

L'insieme di tutte le classi fornite dal Framework .NET prende il nome Base class library. Si tratta di una raccolta vastissima, ed è impossibile anche solo citare tutte le classi che contiene.

Viene poi definito il namespace WindowsApplication1. Tutte le Windows Form create con Visual Studio, così come le classi, le interfacce, gli user control, etc., sono automaticamente inserite all'interno di un namespace, che per impostazione predefinita ha lo stesso nome del progetto.

Questa impostazione può essere cambiata facendo clic con il pulsante destro del mouse sul nome del progetto all'interno del Solution Explorer e selezionando il comando Properties (Proprietà).

VB.NET, al contrario, di default non include le classi create all'interno di namespace.

Il codice evidenzia che anche una Windows Form è una classe, che eredita dalla classe «Form».

Osserviamo la parola chiave partial, una novità della versione 2.0 del Framework che permette di definire classi "parziali".

Di norma, ogni classe risiede in un file separato, ma utilizzando partial è possibile creare classi definite su più file. Da ciascun file parziale è possibile accedere alle variabili, ai metodi, alle proprietà, di tutti gli altri file parziali relativi alla stessa classe, proprio come se l'intera dichiarazione della classe fosse contenuta in un unico file.

Questo nuovo concetto favorisce una maggiore pulizia e leggibilità del codice della Windows Form: il codice di progettazione, che imposta le proprietà della finestra e dei controlli in essa inseriti, in precedenza veniva salvato nello stesso file del form, all'interno della region Windows Form Designer generated code (Codice generato da Progrettazione Windows Form), mentre ora è memorizzato in un file di supporto gestito internamente dall'ambiente di sviluppo e chiamato Form1.Designer.cs (al posto di Form1 c'è il nome del form).

Vedremo che questo concetto somiglia molto a quello di code behind nelle applicazioni Web.

L'unico indizio dell'esistenza di questo file è il metodo InitializeComponent() che viene richiamato nel costruttore del form: esso, come nelle precedenti versioni, ha il compito di inizializzare tutti gli oggetti contenuti nel form.

Per visualizzare il contenuto del file Form1.Designer.cs, premere il pulsante + posto a fianco del nome del form nel Solution Explorer.

In VB.NET, invece, il file del Designer di default è nascosto. Per visualizzarlo, è necessario fare clic sul pulsante Show All Files all'interno del Solution Explorer. Inoltre, in VB la Windows Form non è dichiarata come «Partial» (anche se, in realtà, anch'essa è una classe parziale).

Figura 1. Il Solution Explorer
13a.png

Le classi parziali e il loro utilizzo nelle Windows Form potrebbero sembrare novità di poco conto che, però, si fanno apprezzare quando si crea una finestra con un numero elevato di controlli.

Nelle precedenti versioni il file di definizione della Windows Form si reimpiva di una gran quantità di codice mantenuto dall'ambiente di sviluppo (che, quindi, l'utente non avrebbe dovuto modificare, come indicato chiaramente dai commenti), a discapito della leggibilità.

Visual Studio 2005 consente un posizionamento dei controlli sulla Windows Form molto più agevole che in passato: è sparita la griglia che ricopriva il form in fase di progettazione, poiché ora i controlli sembrano "calamitati" dai bordi della finestra e dagli altri oggetti; inoltre, durante le operazioni di trascinamento, vengono visualizzate delle linee guida per consentire un posizionamento più preciso degli elementi nella finestra.

La gestione degli eventi​
La gestione degli eventi nel Framework .NET 2.0 e in Visual Studio 2005 è rimasta pressoché immutata rispetto alle versioni precedenti.

Continuiamo a lavorare con la Windows Form realizzata nella scorsa lezione, precisando che quanto diremo in seguito a proposito degli eventi vale per ogni tipo di controllo, sia esso una form, un pulsante, una casella di testo, un comando di menu, etc.

Possiamo definire un evento come il verificarsi di una condizione: dalla pressione di un pulsante, alla digitazione in una casella di testo. Quando si verifica una di queste condizioni, diciamo che il controllo genera (oppure lancia) un evento. Ad esempio, quando si preme il pulsante sinistro del mouse su di un bottone, esso genera l'evento «Click».

Ad ogni evento può essere associata una azione descritta da una particolare routine che viene eseguita ogni volta che l'evento si verifica.

Supponiamo di voler eseguire una certa azione in fase di caricamento del form. Occorre anzitutto creare un gestore di eventi (detto Event Handler) per l'evento «Load» della finestra Form1. Aggiungiamo il seguente codice nel costruttore della classe:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Per installare un event handler, occorre specificare il nome dell'oggetto che espone l'evento: in questo caso abbiamo usato this, che, come abbiamo già accennato, rappresenta la classe corrente (in questo caso il form).

Di seguito, dopo il punto, si indica il nome dell'evento da gestire: gli eventi disponibili sono riconoscibili, nell'elenco visualizzato tramite l'IntelliSense, dal simbolo di un fulmine.

Figura 1: Gli eventi del form
14a.gif

L' operatore '+=' indica che si sta aggiungendo un gestore per l'evento. Si usa '+=', e non solo '=', perché è possibile specificare più handler per lo stesso evento.

L'IntelliSense ci viene ancora una volta in aiuto, proponendoci un nome per il gestore degli eventi: è sufficiente premere il tasto TAB per confermare il suggerimento.

Il metodo che rappresenta l'azione collegata all'evento viene detto "delegato" (delegate). Infatti viene delegata a quel metodo la gestione dell'evento. Form1_Load() in questo caso è un delegato.

Questo metodo di creazione degli event handler corrisponde ad «AddHandler» in VB.NET

EventHandler e tutte le classi derivate sono gestori di eventi. Ogni oggetto istanza di EventHanlder richiede il riferimento a un delegato per la gestione di un evento, la stringa "Form1_Load" senza parentesi altro non è che un riferimento (puntatore) al metodo Form1_Load().

Un delegato in astratto ha però una certa firma e per rimpiazzarlo con un altro metodo come Form_Load() occorre che questo abbia i medesimi argomenti in tipo e numero e lo stesso tipo di ritorno.

Con EventHandler(Form1_Load) si esprime il fatto che il metodo Form1_Load() avrà argomenti uguali in numero e tipo a quelli indicati nella dichiarazione del delegate EventHandler e avrà come tipo di ritorno il medesimo tipo del delegate.

Un'altra pressione del tasto TAB aggiunge automaticamente, all'interno della classe, il metodo che sarà richiamato quando si genera l'evento in questione:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
L'istruzione «throw new Exception()» solleva una eccezione. Ci occuperemo delle eccezioni in seguito.

Gli argomenti di questo metodo sono due:

Object sender rappresenta l'oggetto (il controllo, la classe) che ha generato l'evento, ed è utile nel caso in cui la stessa routine venga eseguita in risposta ad eventi lanciati da oggetti diversi, per sapere chi effettivamente lo ha generato;
EventAgrs e. EventArgs, come pure tutte le classi da essa derivate, contiene gli argomenti associati all'evento. Nel nostro caso «e» è di tipo EventArgs, ma, può essere specializzata a seconda dell'evento.
Ad esempio, nel caso di eventi di gestione del mouse (MouseClick,MouseMove, etc.), è di tipo «MouseEventArgs» e permette di conoscere la posizione del cursore o quale tasto del mouse è stato premuto.
Proviamo ad utilizzare la routine Form1_Load. Vogliamo fare in modo che, all'avvio del programma, venga visualizzata una MessageBox con la scritta "Ciao Mondo!". A tal scopo, è sufficiente definire il metodo Form1_Load nel modo seguente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
MessageBox è una classe che contiene un metodo statico, Show() che visualizza una finestra di messaggio. Esso dispone di parecchie definizioni tramite overloading (21 per la precisione); la versione più utilizzata, anche da noi, prende come argomenti il messaggio da visualizzare, il titolo della MessageBox, i pulsanti e l'icona della finestra.

Eseguiamo ora l'applicazione facendo clic sul pulsante
play.gif
della barra degli strumenti (oppure premendo il tasto F5). Se non sono stati commessi errori, dopo la compilazione dovrebbe comparire la finestra riportata in figura.

Figura 2: L'output del programma
14b.gif

Gli event handler possono essere creati anche in un altro modo. All'interno della finestra di progettazione, selezionare il controllo per cui si vuole definire il gestore, quindi spostarsi nella finestra Properties (Proprietà) e fare clic sull'icona raffigurante un fulmine.

Comparirà un elenco contenente tutti gli eventi generati dal controllo in questione. Selezionandone uno, nella parte bassa della finestra sarà visualizzato un breve messaggio che indica quando tale evento viene lanciato.

Clicchiamo su un evento, digitiamo il nome di una routine nella casella di testo corrispondente e premiamo il tasto INVIO, Visual Studio aggiungerà automaticamente il codice per installare l'event handler (all'interno del file del Designer) ed inserirà nel file del form una routine con il nome indicato.

In alternativa, facendo doppio clic sul nome dell'evento, sarà creato un event handler e una routine di gestione con il nome predefinito (formato da nome del controllo, trattino basso e nome dell'evento).

Per eliminare un gestore degli eventi creato in questo modo, fare clic con il tasto destro del mouse sull'evento e selezionare il comando Reset (Annulla). Infine, per tornare alla visualizzazione delle proprietà del controllo, premere il pulsante Properties (Proprietà) che si trova a sinistra dell'icona con il fulmine.

Figura 3: La finestra per la definizione degli event handler

14c.gif

Ancora, facendo doppio clic su di un oggetto, Visual Studio definirà automaticamente un event handler per l'evento predefinito dell'oggetto in questione (Load per i form, Click per i pulsanti, TextChanged per le caselle di testo, ecc.).

L'esempio che abbiamo realizzato può essere scaricato cliccando
Perfavore, Entra oppure Registrati per vedere i Link!


Questa rapida panoramica sulla Windows Form ha lo scopo di fornire le conoscenze di base che permettano di approfondire l'argomento senza troppa fatica. Per una discussione più dettagliata, si rimanda ai riferimenti a fondo pagina alla guida a VB.NET: nonostante il linguaggio sia differente, i concetti esposti risultano validi anche per C#.

Controlli Windows​
Il framework .NET mette a disposizione una nutrita serie di oggetti che possono essere inseriti in una Windows Form , i cosiddetti Windows Controls (Controlli Windows o, più semplicemente, Controlli).

Sono gli oggetti più comuni a tutte le interfacce grafiche come bottoni, checkbox, etc., ma troviamo anche controlli per la gestione di dati o per il dialogo con le periferiche.

Tutti impacchettati in classi con metodi e proprietà che ne permettono la personalizzazione a seconda delle esigenze, i controlli consentonto di realizzare applicazioni dall'aspetto professionale con uno sforzo minimo.

Dato il loro numero (più di 60), è impossibile analizzarli tutti in questa sede: ci limiteremo a mostrare quali sono le novità dei principali controlli del Framework 2.0, rimandando alla guida su VB.NET (ed alla guida in linea di Visual Studio) per maggiori dettagli sugli altri oggetti.

All'interno della Casella degli strumenti di Visual Studio 2005 (Toolbox in inglese), i controlli sono divisi in categorie:

All Windows Forms: che visualizza in un'unica scheda tutti i controlli disponibili;
Common Controls, che contiene gli oggetti tipicamente presenti in ogni finestra (Label, TextBox, Button, ListBox, ComboBox, etc.);
Containers, che raggruppa i controlli che permettono di gestire il layout del form, ovvero la disposizione degli oggetti;
menù & Toolbars, contenente oggetti che permettono di aggiungere barre dei menù, barre degli strumenti, barra di stato e menù contestuali all'applicazione;
Data, che contiene gli strumenti che permettono di lavorare con fonti di dati esterne (come i database);
Components, che raggruppa oggetti i quali consentono di interagire con il sistema operativo (per gestire le Active Directory ed il registro eventi di Windows, monitorare le modifiche al file system, etc.);
Printing, che contiene gli oggetti necessari per aggiungere le funzionalità di stampa all'applicazione;
Dialogs, contenente i controlli che consentono di visualizzare le finestre di dialogo comuni di Windows, come Apri e Salva con nome.
Figura 1. Toolbox di Visual Studio 2005
15a.gif

Controlli come TextBox, ListBox e PictureBox sono stati aggiornati con l'aggiunta di alcune proprietà e funzioni, ma il loro utilizzo è rimasto essenzialmente uguale rispetto alle versioni precedenti di .NET .

I controlli MenuStrip (barra dei menù) e ToolStrip (barra degli strumenti), sono stati notevolmente potenziati e supportano lo stile introdotto con Office 2003:

Figura 2. Nuovo stile per barra menù e strumenti

15b.gif

Essi sostituiscono i vecchi controlli MainMenu e ToolBar. Al loro interno è ora possibile inserire un numero maggiori di elementi: un menù, infatti, può contenere anche TextBox e ComboBox, così come la barra degli strumenti, che è in grado di ospitare anche ProgressBar. Il MenuStrip, inoltre, consente di associare icone alle voci di menù.

Anche il controllo StatusStrip, sostituto del vecchio StatusBar ed utilizzato per visualizzare una barra di stato nell'applicazione, ha subito le stesse operazioni di aggiornamento.

Un'altra novità è rappresentata dai controlli per gestire il layout della finestra, contenuti nella sezione Containers della «Casella degli strumenti». Accanto ai controlli già presenti nelle versioni del Framework, infatti, sono stati inseriti oggetti come FlowLayoutPanel e tableLayoutPanel, che consentono di disporre automaticamente i controlli inseriti al loro interno.

Mostriamo ora un semplice esempio d'uso di alcuni controlli realizzando una piccola applicazione per Windows: un visualizzatore di immagini minimale, composto da una casella di testo in cui digitare il percorso del file, un pulsante per visualizzare la finestra di dialogo «Apri» e un pulsante che mostra l'immagine selezionata in una PictureBox.

Una CheckBox permetterà di stabilire se si vuole visualizzare l'immagine nelle sue dimensioni reali oppure ingrandita a occupare tutta l'area disponibile.

Figura 3. Interfaccia della applicazione esempio
15c.gif


Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare il progetto.

Non ci resta che scrivere il codice da associare agli eventi dei controlli. Anziutto vogliamo che, cliccando sul pulsante btnSfoglia, si apra la finestra di esplorazione per selezionare un'immagine.

Per associare automaticamente un Event Handler all'evento principale di un determinato oggetto, è sufficiente un doppio click sull'oggetto in questione. Nel nostro caso definiamo l'event handler per l'evento «Click» del pulsante. Nella finestra del codice appare la definizione del metodo delegato e possiamo aggiungere il codice di gestione dell'evento:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il metodo ofdApri.ShowDialog() visualizza la finestra di dialogo per la selezione di un file; il tipo del file è indicato nella proprietà Filter del controllo.

La routine restituisce un valore di tipo DialogResult che permette di conoscere il motivo della chiusura della finestra: DialogResult.OK indica che la finestra è stata chiusa perché l'utente ha premuto il pulsante «OK» (se viene premuto «Annulla», il valore restituito è DialogResult.Cancel).

Il nome del file selezionato è salvato nella proprietà FileName del controllo.

Ora dobbiamo visualizzare l'immagine selezionata. Facciamo doppio clic sul pulsante «bntVisualizza» e scriviamo questa semplice istruzione:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Per caricare l'immagine, abbiamo usato il metodo statico FromFile() della classe Bitmap, contenuta nel namespace System.Drawing, il quale prende come argomento il nome di un file e restituisce un oggetto che rappresenta l'immagine in esso contenuta. A questo punto, è sufficiente assegnarlo alla proprietà Image del controllo picImmagine perché venga visualizzata.

Ci resta solo da definire il comportamento dell'applicazione sul click del pulsante con chkAdattaImmagine spuntata:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
CheckedChanged è l'evento che viene generato quando si fa clic sulla checkBox.

Queste istruzioni fanno sì che, quando la casella è selezionata, ovvero la proprietà «Checked» vale true, la proprietà «sizeMode» della PictureBox venga imposta su PictureBoxsizeMode.StretchImage, in modo che l'immagine si adatta all'area disponibile.

La nostra applicazione è pronta. Possiamo eseguirla premendo il tasto F5 per verificare che il suo comportamento sia quello desiderato.

L'esempio completo è disponibile per il download cliccando qui.

A causa di un bug della versione Beta 2 di Visual Studio 2005 e del Framework .NET 2.0, cambiando la proprietà sizeMode a tempo di esecuzione, l'altezza del controllo PictureBox diminuisce; tale comportamento può essere ignorato, poiché verrà sicuramente risolto con la versione definitiva del Framework .NET 2.0, e comunque è facilmente aggirabile facendo in modo che, ogni volta che si cambia la proprietà sizeMode, la dimensione del controllo venga reimpostata sul valore iniziale.

Le eccezioni​
Fino a questo punto del corso non abbiamo mai parlato della gestione degli errori in C#. Semplificando, un errore è il verificarsi di una situazione imprevista durante l'esecuzione di un programma.

Gli errori nel mondo .NET, nella migliore tradizione Object Oriented (Java, C++, etc.) vengono rappresentati con le eccezioni: una intera gerarchia di classi per la gestione degli eventi indesiderati.

Le eccezioni vengono "sollevate" al verificarsi di una situazione anomala, come un errore. Si possono ignorare, con il rischio di avere delle brutte sorprese a run-time, oppure si possono intercettare e gestire.

Questo implica l'uso di un costrutto nato appositamente per l'intercettazione delle eccezioni: try-catch-finally.
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Se il codice che viene eseguito all'interno del blocco try solleva una eccezione, questa viene catturata e viene eseguito il blocco catch. In ogni caso viene eseguito poi anche il blocco finally.

Nel costrutto try-catch è necessario specificare almeno una clausola catch oppure una finally; si possono indicare più catch, una per ogni tipo di errore che si vuole gestire, mentre è consentito inserire solo una clausola finally.

Nella clausola catch si può indicare il tipo di eccezione che si vuole gestire; ad esempio:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il primo blocco catch viene eseguito se si verifica un errore di overflow, ad esempio quando si cerca di assegnare ad una variabile un valore al di fuori del suo range di definizione. Il secondo viene invocato se si effettua una divisione per 0.

In entrambi i casi, l'oggetto «ex» contiene varie informazioni sull'errore. Ad esempio, la proprietà ex.Message restituisce una stringa di descrizione della causa dell'eccezione.

Aggiorniamo ora l'applicazione che abbiamo realizzato nella lezione precedente aggiungendo la gestione degli errori. In particolare, consideriamo l'istruzione
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Nel caso in cui il file specificato non esista, il metodo FromFile lancia un'eccezione di tipo FileNotFoundException. Inseriamo, quindi, tale istruzione in un blocco try...catch:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Dal momento che anche le eccezioni sono classi, anch'esse sono raggruppate all'interno di namespace. Per esempio, perché il Framework sappia dove cercare la classe FileNotFoundException, tra le clausole «using» va aggiunta quella relativa al namespace «System.IO».

Ogni volta che, cercando di caricare un file, si verifica un'eccezione di tipo «FileNotFoundException», viene eseguito il blocco catch corrispondente, il quale visualizza una finestra di messaggio. L'errore di file non trovato, però, non è l'unico che può capitare quando si cerca di aprire un file: ad esempio, se la memoria a disposizione non è sufficiente per completare il caricamento, si ottiene un errore di tipo OutOfMemoryException.

Ancora, se si preme il pulsante «Visualizza» senza aver digitato alcun nome di file, si verifica una ArgumentException.

Aggiungiamo, quindi, un secondo blocco catch per trattare tutti gli altri casi, ottenendo complessivamente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Poiché Exception è la classe base da cui derivano tutte le altre eccezioni, il secondo blocco catch è eseguito ogni volta che il metodo FromFile lancia un'eccezione che non sia di tipo «FileNotFoundException» (e che non derivi da essa).

In questo caso abbiamo usato l'informazione contenuta nell'eccezione «ex» per sapere con esattezza l'origine dell'errore.

L'esempio completo è disponibile
Perfavore, Entra oppure Registrati per vedere i Link!


È sempre meglio evitare la gestione delle eccezioni, cercando di prevedere, dove possibile, le cause che possono portare ad una situazione imprevista: un abuso di try...catch, infatti, può appesantire molto un programma. Nel nostra applicazione, ad esempio, l'errore ArgumentException può sempre essere evitato semplicemente facendo in modo che il metodo FromFile venga richiamato solo se è stato digitato qualcosa nella casella di testo.

Programmazione web: C# e ASP .NET​
Il volto Web del Framework .NET è meglio noto come ASP .NET. A dispetto del nome ASP .NET ha ben poco a che fare con il predecessore ASP: esso riesce a portare la potenza della programmazione ad oggetti tipica di C# e di VB.NET anche nella realizzazione di applicazioni Web.

I mondi delle applicazioni desktop e delle applicazioni web convergono con .NET. È stato introdotto un modello di programmazione per il Web che ha permesso ai programmatori VB e C# di trasferire le proprie competenze di sviluppo Windows in ambito Web e viceversa.

Per realizzare ed eseguire un'applicazione Web con ASP .NET è necessario che nel sistema sia installato il framework .NET ed un web server in grado di interpretare ed eseguire i file ASP .NET, che hanno estensione .aspx.

Visual Studio 2005 include un tool di sviluppo Web completamente rinnovato, Visual Web Developer, che integra un piccolo server Web per consentire a tutti di sperimentare da subito le potenzialità di ASP .NET.

ASP.NET fornisce un ambiente orientato agli oggetti e basato sugli eventi per le applicazioni Web. Le pagine non sono altro che classi C# o VB.NET con le caratteristiche che abbiamo già introdotto. Esse ereditano le funzionalità di base dalla classe «Page» come una Windows Form eredita dalla classe «Form».

Realizziamo una prima applicazione Web con Visual Studio 2005. Ne approfitteremo per introdurre i primi concetti relativi alla gestione delle pagine ASP.NET . Dopo aver avviato l'ambiente di sviluppo, selezioniamo dal menù File>new e clicchiamo sulla voce «Web Site» (Sito Web). Appare una finestra di dialogo:

Figura 1. La finestra di dialogo New Web Site
17a.gif

Scegliamo «ASP .NET Web Site», quindi, nella parte bassa della finestra, indichiamo che la locazione del sito è il file system (le altre opzioni sono HTTP e FTP) e che il linguaggio utilizzato è C#. clicchiamo su «OK» e Visual Studio crea una soluzione contenente un file di nome «Default.aspx» (la pagina iniziale del sito) e uno contenente il cosiddetto code behind della pagina, chiamato «Default.aspx.cs».

Questa caratteristica è molto importante: tutto il codice degli script della pagina, che in genere è "immerso" all'interno dell'HTML, ora può risiedere anche in un file separato, consentendo una separazione tra grafica e codice.

Figura 2. Il Solution Explorer di Visual Web Developer
17b.gif

Cliccando con il pulsante destro su «Default.aspx» e selezionando «View Designer» (Visualizza Progettazione) si apre l'editor visuale della pagina Web.

La casella degli strumenti sulla sinistra ospita un gran numero di controlli divisi in varie categorie. Per il momento ci interessano quelli che si trovano nella categoria Standard, la quale contiene una serie di controlli simili a quelli per le applicazioni desktop.

Figura 3. La toolbox di Visual Web Developer
17c.gif

Con un doppio clic sul controllo «Label», inseriamo nella pagina un'etichetta; sulla destra, nella finestra «Properties», saranno visualizzate le proprietà dell'oggetto, le modifichiamo come indicato di seguito (la proprietà ID corrisponde alla proprietà Name dei controlli Windows):

HTML:
Perfavore, Entra oppure Registrati per vedere i codici!

Proviamo ad eseguire l'applicazione ASP .NET finora realizzata. Il progetto si avvia come se si trattasse di un'applicazione Windows, quindi premendo il tasto F5 oppure il pulsante sulla barra degli strumenti.

La prima volta che l'applicazione viene lanciata comparirà una finestra che chiede se si vuole attivare il debug per il sito Web, selezioniamo l'opzione Add new Web.config file with debugging enabled e confermiamo con «OK»: fatto ciò, verrà avviato il server Web integrato in Visual Web Developer e l'applicazione ASP .NET sarà visualizzata all'interno del browser Web predefinito.

Nel caso in cui abbiamo un progetto composto da più pagine, per scegliere quale mostrare nel browser è sufficiente selezionarla nel Solution Explorer prima di avviare l'esecuzione (non è necessario impostarla come pagina di avvio, come si doveva fare con le precedenti versioni di Visual Studio).

Per il momento, l'unica cosa che appare nella pagina è la stringa "Ora di connessione", come si trattasse di una pagina statica.

Chiudiamo il browser e torniamo in Visual Studio per aggiungere una prima componente dinamica. Con un doppio clic su un punto vuoto della pagina all'interno dell'editor aggingiamo automaticamente il gestore dell'evento Load, che viene inserito nel "code behind" della pagina ovvero nel file «Default.aspx.cs».
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
La firma dell'evento è esattamente la stessa dell'evento Load di una Windows Form. Anche il significato è lo stesso: il codice inserito in questo metodo verrà eseguito ogni volta che la pagina sarà caricata. Vogliamo fare in modo che, ogni volta che si apre o si aggiorna la pagina, l'etichetta definita in precedenza contenga la data e l'ora dell'operazione. Scriviamo:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il codice della pagina «Default.cs» non ha bisogno di modifiche. Proviamo ora ad eseguire l'applicazione. Se non sono stati commessi errori, nel browser Web dovrebbe apparire qualcosa di simile a:

Figura 4. Esecuzione del programma
17d.gif

L'esempio realizzato può essere scaricato cliccando
Perfavore, Entra oppure Registrati per vedere i Link!


Web form​
Così come la Windows Form è il componente base di ogni applicazione per Windows, la Web Form è il centro di un'applicazione ASP .NET.

Con Visual Web Developer è possibile costruire graficamente una Web Form proprio come si fa con la Windows Form, utilizzando controlli simili per aspetto e proprietà: è poi l'editor che, in modo del tutto automatico, si preoccupa di produrre "dietro le quinte" il codice HTML necessario per visualizzare gli elementi dell'interfaccia all'interno del browser Web.

Scendendo nei dettagli dell'implementazione, una Web Form è una pagina Web in cui tutti gli elementi (testo, elenchi, pulsanti, caselle, ecc.) sono inseriti all'interno di una normale form HTML, ovvero tra i tag <form> e </form>.

Per leggere il codice HTML è sufficiente fare clic sul pulsante «Source» (Sorgente) visualizzato nella parte bassa del Designer.

Figura 1. Modalità di visualizzazione di una pagina ASP .NET
18a.gif

Anche la Web Form è un oggetto al pari di tutti gli elementi in essa contenuti, per cui è possibile accedere a metodi e proprietà. Inoltre dal codice di una pagina è possibile accedere all'intera libreria di classi di .NET . Abbiamo già visto un esempio di come utilizzare la classe DateTime per recuperare la data e l'ora di sistema.


PostBack
Quando la pagina viene caricata all'interno del browser, viene generato l'evento Page_Load. Nel codice del delegato per Page_Load è possibile verificare se l'utente sta effettuando il primo accesso alla pagina oppure sta effettuando un PostBack.

La tecnica del postback è quella che consente ad una pagina Web di trasmettere a se stessa delle informazioni di stato.

In pratica in una pagina web dinamica viene creato un form che ha come campo «action» l'indirizzo della pagina stessa ed al suo interno dei campi «hidden» che mantengono informazioni sullo stato della pagina. Per esempio potremmo avere un campo che contiene il testo di una casella di testo. Molto spesso vengono usati campi «hidden» per ricordare se includere una porzione di codice o meno.

Queste informazioni una volta generato un evento "Submit" (che non necessariamente scaturisce da un bottone), vengono "rispedite indietro" alla pagina che le usa per modificare il suo aspetto.

Questa tecnica è abbastanza comune per chi programma in ASP o PHP, ma ASP.NET l'ha intergata nel concetto di Web Form con il PostBack e il ViewState che vedremo tra breve

La proprietà IsPostBack restituisce il valore true quando il modulo presente nella pagina è stato eseguito, false quando si tratta del primo accesso alla pagina:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Esempio
Realizziamo ora una piccola applicazione Web. Vogliamo fare in modo che l'utente possa digitare il suo nome e, premendo un pulsante, riceva un messaggio di saluto.

Usiamo i controlli della categoria Standard della Toolbox. Per aggiungere un oggetto alla Web Form è sufficiente fare doppio clic su di esso nella casella degli strumenti, una volta inserito può essere spostato utilizzando il mouse, come si fa per i Controlli Windows. Posizioniamo così la Label lblNome.

trattandosi di un normale form HTML, inoltre, è possibile scrivere direttamente del testo all'interno della pagina. La Web Form dovrebbe risultare simile a quella visibile in figura.

Figura 2. Il layout della pagina
18b.gif

Impostiamo le proprietà degli oggetti come indicato nella tabella seguente:

HTML:
Perfavore, Entra oppure Registrati per vedere i codici!

Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare la pagina.

Visualizziamo il sorgente ed analizziamo il codice della pagina. Osserviamo che al pulsante «Conferma» è associata la riga:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Ogni oggetto è descritto da un tag in formato XML dove gli attributi specificano le proprietà dell'oggetto.

Aggiungiamo il delegato per la pressione del bottone. Torniamo in modalità Design e facciamo doppio clic sul bottone per definire l'event handler corrispondente al «Click». L'ide ci mostrerà il file con il "code behind" della pagina ed avrà preparato per noi la dichiarazione del delagato. A questo punto è sufficiente scrivere:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Nel sorgente della pagina è stato automaticamente aggiunto il tag OnClick="btnConferma_Click" all'oggetto «asp:Button» definito in precedenza: poiché si tratta di un controllo lato server (ovvero di un controllo con l'attributo runat="server" contraddistinto, nel Designer, da una freccina verde in alto a sinistra).

In questo modo si istruisce il server che, alla pressione del pulsante, quando verrà eseguito il PostBack della pagina, deve essere richiamato il metodo btnConferma_Click contenuto nel code behind.

La nostra applicazione è pronta per l'esecuzione. Avviamola, digitiamo un nome nella casella di testo e premiamo il pulsante. Otteniamo:

Figura 3. L'output del programma
18c.gif

Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare l'esempio.

Proviamo a visualizzare il sorgente della pagina all'interno del browser Web (ad esempio, in IExplorer, con il comando Visualizza>HTML), notiamo che tutto il codice ASP .NET è stato tradotto in HTML standard.

Non c'è però traccia del codice dello script. Esso, in modo del tutto invisibile, è stato compilato in una libreria che risiede sul server e che viene richiamata ogni volta che si effettua il post della pagina (abbiamo infatti detto che una Web Form è un particolare tipo di form HTML).


Viewstate
Continuando ad osservare il sorgente, notiamo che nella form è stato inserito anche un campo nascosto di nome __VIEWSTATE, che può apparire nel modo seguente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il ViewState è una tabella associativa codificata che contiene lo stato degli oggetti presenti nella form, ad esempio il testo inserito in una casella oppure quali CheckBox sono state selezionate.

HTTP è un protocollo stateless (senza stato), ovvero non mantiene informazioni sullo stato di una pagina tra una visita e l'altra: per sopperire a tale mancanza, ASP .NET utilizza il campo ViewState.

Ogni volta che si ricarica una pagina, i controlli in essa presenti vengono inizializzati sulla base del contenuto del ViewState, che viene generato automaticamente da ASP .NET . Questa soluzione consente di trasferire lo stato dei controlli dal server al client e viceversa.

Ciò significa che quando il server leggerà il ViewState di una pagina sarà in grado di ripristinare, ad esempio, il valore corrente di tutti i campi «input», senza bisogno che sia il programmatore a farlo via codice.

trattandosi di una tabella associativa, inoltre, nel ViewState è possibile inserire anche dei valori personalizzati. Ad esempio, possiamo memorizzare nel ViewState il numero di volte in cui il pulsante Conferma è stato premuto:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
In questo caso, leggiamo il valore associato alla chiave click nel ViewState: se non è stato ancora inizializzato (ovvero vale null), significa che questa è la prima pressione del pulsante, altrimenti incrementiamo il valore in esso contenuto. Dopo aver stampato il numero di clic, aggiorniamo il contenuto del ViewState. Qunidi ad ogni pressione del pulsante il numero stampato aumenterà.

È possibile scaricare la nuova versione della pagina
Perfavore, Entra oppure Registrati per vedere i Link!


Il ViewState è mantenuto solo se vengono eseguite richieste consecutive della stessa pagina: nel caso in cui venga caricata una nuova pagina, il ViewState sarà perso.

Per mantenere le informazioni durante la navigazione, è possibile ricorrere all'oggetto Session. Anch'esso si comporta come una tabella associativa e funziona esattamente come il ViewState, tuttavia le variabili archiviate al suo interno non vengono cancellate quando l'utente passa da una pagina a un'altra dell'applicazione, ma sono mantenute per tutta la "sessione" che inizia quando un browser punta al nostro sito e finisce quando viene chiusa.

I controlli Web​
Come per le Windows Form anche nello sviluppo di Web Form troviamo l'aiuto di controlli che prendono il nome di Web Controls (Controlli Web).

Al pari dei controlli Windows, anche i controoli Web sono raggruppati in categorie nella Casella degli strumenti. In questa guida ci limiteremo a parlare dei controlli della categoria Standard, che comprende, tra gli altri:

Label, TextBox, Button (che abbiamo già incontrato);
DropDownList, ListBox;
CheckBox, RadioButton;
CheckButtonList, RadioButtonList, che consentono di raggruppare, rispettivamente, un insieme di CheckBox oppure di RadioButton;
Image, ImageMap, ImageButton;
table.
Figura 1. Toolbox di Visual Web Developer
19a.gif

Come al solito ci aiuteremo con un esempio pratico. Realizziamo una Web Form in cui inserire i propri dati personali, che verranno poi inviati ad un indirizzo di posta elettronica.

Dopo aver creato un nuovo progetto Web, aggiungiamo i controlli alla Web Form in modo da ottenere un'interfaccia analoga a quella visibile in figura:

Figura 2. Il layout della pagina
19b.gif

Le proprietà degli oggetti sono riassunte nella tabella seguente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il titolo della form è un testo scritto direttamente nella pagina all'interno del Designer.

È possibile scaricare
Perfavore, Entra oppure Registrati per vedere i Link!
la Web Form creata finora.

Passiamo alla scrittura del codice. Selezionando l'ultima voce della lista che contiene gli hobbies, vogliamo che appaia la casella di testo in cui digitare il nome del passatempo. Allo stesso modo, se si clicca su un'altra opzione, questa TextBox deve essere nascosta.

Clicchiamo due volte sul controllo «lstHobby» per definire l'event handler predefinito, ovvero SelectedIndexChanged, quindi scriviamo:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Avviamo l'applicazione. Cliccando su "(Altro)" compare la casella di testo, mentre con qualsiasi altra selezione essa viene nascosta.

La form si comporta in questo modo perché abbiamo impostato la proprietà AutoPostBack della ListBox su true.

Infatti AutopostBack è a true qualunque evento il controllo scateni viene provocato un Submit() ovvero in PostBack e viene ricaricata la pagina.

In questo caso, ogni volta che si seleziona un elemento diverso della lista viene effettuata una richiesta al server, il quale esegue il codice corrispondente all'evento SelectedIndexChanged.

Lasciando tale proprietà su false (valore predefinito) invece il PostBack viene causato da un altro evento, tipicamente la pressione di un bottone.

Talvolta, per forzare l'invio anche in seguito ad altre azioni, si ricorre a codice JavaScript introducento una chiamata a Submit(). Anche ASP .NET usa questo metodo, ma lo "nasconde" nella proprietà AutoPostBack: quando vale true, tra i tag del controllo viene automaticamente aggiunta una chiamata a Submit()

Per verifica impostiamo la proprietà AutoPostBack del controllo «lstHobby» su false ed eseguiamo nuovamente l'applicazione. Questa volta, la selezione degli elementi non determina una richiesta al server. L'evento SelectedIndexChanged sarà generato solo in seguito alla pressione del pulsante Invia.

Aggiungiamo il codice da eseguire sul «Click» del pulsante, che deve inviare via mail le informazioni inserite nella Web Form:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Per utilizzare la classi MailMessage e SmtpClient, è necessario aggiungere una clausola
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Per completare l'applicazione, è sufficiente indicare il valore delle variabili «Destinatario» e «MailServer», che devono contenere, rispettivamente, l'indirizzo di posta a cui verranno spediti i dati inseriti nella form e il server mail usato per l'invio, ad esempio news.tin.it.

Per scaricare la Web Form completa, cliccare
Perfavore, Entra oppure Registrati per vedere i Link!


Sono disponibili anche dei controlli per la verifica degli input degli utenti. Si usano come tutti i controlli e permettono, ad esempio, la verifica che il nome e l'indirizzo di mail siano stati effettivamente digitati ed il formato degli indirizzi.

Creare un web user control​
I numerosi controlli Web disponibili con il Framework .NET 2.0 consentono di creare pagine ASP .NET ricche di funzionalità, dalla visualizzazione di un'immagine al recupero di dati da un database.

In alcune situazioni, tuttavia, potrebbero essere necessari oggetti più sofisticati di quelli predefiniti: in questo caso possiamo creare un Web User Control (Controllo utente), utilizzando le stesse tecniche introdotte nelle scorse lezioni.

In effetti, un Web Control può essere costruito come una Web Form: anch'esso è dotato di un'interfaccia utente e di un file con il code behind; a differenza di una Web Form, tuttavia, è contenuto in un file con estensione ".ascx" e non può avere i tag <HTML>, <BODY> e <FORM> poiché viene inserito in una Web Form che questi tag li contiene già.

Anche un Web User Control è una classe ed eredita le sue funzionalità di base da System.Web.UI.UserControl.

Per definire un Web User Control, dopo aver creato un nuovo sito ASP .NET facciamo clic con il tasto destro del mouse sul nome del progetto all'interno del Solution Explorer e selezioniamo il comando «Add New Item...» (Aggiungi nuovo elemento).

Si aprirà una finestra di dialogo in cui sono mostrati tutti i tipi di file che possono essere aggiunti. Selezioniamo «Web User Control» e impostiamo il nome del file e il linguaggio in cui scrivere il code behind.

Grazie al runtime comune del Framework .NET è possibile avere una Web Form scritta in C# al cui interno si trova un Web Control realizzato con Visual Basic .NET, e viceversa.

Figura 1. La finestra di dialogo Add New Item
20a.gif

Confermiamo premendo il pulsante «Add» (Aggiungi). Il nuovo Web Control sarà al aggiunto progetto, insieme al file contenente il code behind.

A questo punto si aprirà automaticamente la visualizzazione della pagina sorgente. Passando al Designer, ci troviamo di fronte allo stesso editor visuale con cui si creano le Web Form.

Creiamo un semplice controllo composto da una Label e da una TextBox visto che questi due elementi sono spesso utilizzati in coppia, avere un Web Control che li definisce entrambi in una sola volta permette di risparmiare tempo nella creazione delle pagine.

L'interfaccia dovrebbe risultare come la seguente:

Figura 2. Il layout del Web User Control
20b.gif

L'impostazione delle proprietà è semplice:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare il controllo.

Aggiungiamo le proprietà che consentono di lavorare con l'etichetta e la casella di testo. Dal momento che il Web Control, una volta inserito in una pagina ASP .NET, viene visto come un unico oggetto, deve disporre di proprietà che permettano di modificare gli oggetti contenuti al suo interno.

Nel file del code behind definiamo le proprietà Caption e Text, per leggere e cambiare, rispettivamente, il testo dell'etichetta e il contenuto della casella:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il nostro Web User Control è completo e può essere prelevato cliccando qui .

Aggiungiamo questo controllo ad una pagina ASP .NET. Visualizziamo la Web Form in cui inserire l'oggetto, quindi, all'interno del Solution Explorer, clicchiamo sul nome del Web Control (il nome predefinito è WebUserControl.ascx).

trasciniamolo nella posizione desiderata della pagina: una volta rilasciato il mouse, il nostro Web User Control sarà visualizzato.

La finestra delle proprietà dell'oggetto dovrebbe mostrare anche le proprietà che abbiamo definito in precedenza; se così non fosse, è sufficiente chiudere la pagina, salvare il controllo e riaprirla.

I valori di Caption e di Text possono essere impostati sia in fase di progettazione, utilizzando la finestra delle proprietà, sia da codice, ad esempio:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Modificando una proprietà in fase di progettazione, il Web Control non verrà aggiornato con i nuovi valori, che, però, saranno correttamente visualizzati quando si caricherà la pagina nel browser.

Se ora diamo uno sguardo al sorgente della Web Form, notiamo che, quando si aggiunge un Web Control ad una pagina, in essa viene inserita la direttiva @Register: si tratta di una sorta di "include" e specifica che nella pagina si utilizza un controllo il cui codice è contenuto in un file esterno.

Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare un esempio di utilizzo del controllo all'interno di una Web Form.

La Web Control Library​
Oltre ai Web User Control il Framework .NET mette a disposizione un altro metodo per creare nuovi controlli Web: la definizione di una Web Control Library.

La differenza principale tra i due tipi di controlli riguarda la fase di progettazione e consiste nella semplicità di creazione da una parte e nella facilità d'uso dall'altra. I controlli Web sono semplici da creare, dal momento che si realizzano in maniera visuale, dispongono del code behind e supportano la gestione degli eventi.

Tuttavia, un Web User Control non può essere aggiunto alla Casella degli strumenti ed è rappresentato in maniera statica quando viene aggiunto ad un pagina (ovvero la modifica di una sua proprietà non si riflette nelle visualizzazione all'interno del Designer, ma è visibile solo in fase di esecuzione).

Inoltre, l'unico modo di condividere il controllo tra applicazioni diverse consiste nell'inserirne una copia distinta in ciascun progetto, soluzione che richiede una maggiore gestione nel caso in cui si apportino modifiche al controllo.

Una Web Control Library invece in genere si realizza scrivendo a mano il codice che poi sarà compilato. Dunque è più difficile da realizzare. Una volta realizzato il controllo, tuttavia, è possibile aggiungerlo alla Casella degli strumenti e gestirlo in modo analogo a quanto visto per i controlli standard.

Proviamo a creare una Web Control Library, cercando di analizzare le caratteristiche principali di questo tipo di controlli.

Dopo aver creato un sito ASP .NET, aggiungiamo un progetto alla soluzione e selezioniamo come tipo di progetto "Web Control Library", come evidenziato in figura.

Figura 1. La finestra di dialogo Add Project
21a.gif

L'editor di Visual Studio aprirà automaticamente il file "WebCustomControl1.cs". Analizziamo il codice inserito di default nel file (alcune parti sono state omesse per motivi di spazio):
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Ogni controllo estende la classe WebControl, che fornisce proprietà, metodi ed eventi comuni a tutti i controlli server Web.

Alla dichiarazione della classe ed alla proprietà "Text" sono stati aggiunti, tra parentesi quadre, i cosiddetti Custom Attributes, ovvero una serie di attributi che forniscono informazioni aggiuntive sulle classi, sui metodi e sulle proprietà.

Ad esempio, ToolboxData indica quale tag è associato al controllo: in pratica, quando tale controllo sarà inserito in una pagina, esso sarà identificato dal tag specificato in questo attributo. Ancora, Category specifica la categoria in cui sarà visualizzata la proprietà Text all'interno della visualizzazione per categorie della finestra Properties.

Un'analisi dettagliata dei Custom Attributes esula dagli obiettivi di questo corso, per cui si rimanda alla guida in linea.

Concentriamoci invece sul metodo Render(), il "cuore" del Web Control: esso, infatti, specifica qual è il codice HTML che deve essere inserito nella pagina per visualizzare il controllo. Questa routine riceve come argomento un oggetto di tipo HtmlTextWriter su cui scrivere il codice HTML.

Senza scendere nei dettagli, il metodo Render() viene automaticamente richiamato dal runtime del Framework sia quando il controllo è visualizzato in una pagina ASP .NET nel Visual Web Developer, sia quando deve essere generato il contenuto HTML da inviare al browser.

Nel primo caso, output rappresenta la pagina all'interno dell'editor, nel secondo si riferisce alla pagina che viene inviata al client per la visualizzazione nel browser (in pratica, il codice HTML che viene scritto dal metodo Render() è il codice che l'utente riceve quando richiede la pagina al server).

Anche i controlli Web standard si comportano nello stesso modo: ogni controllo inserito in una pagina genera il codice HTML necessario alla sua visualizzazione tramite il metodo Render().

Ad esempio, la routine Render() di un controllo Label produce il seguente codice HTML:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Tornando al nostro Web Custom Control, la sua routine Render() si limita a scrivere nella pagina il contenuto della variabile text, senza aggiungere alcuna formattazione HTML. Proviamo ad inserire questo controllo in una Web Form.

Anzitutto dobbiamo compilare il file DLL che sarà utilizzato dall'applicazione ASP .NET. Dopo esserci assicurati che il progetto selezionato nel Solution Explorer sia "WebControlLibrary1", clicchiamo su comando Build>Build ebControlLibrary1.

Ora apriamo il file "Default.aspx" in visualizzazione design. La Toolbox si è arricchita di una nuova scheda che corrisponde alla nostra Web Control Library: essa contiene una voce per ogni classe che estende WebControl contenuta al suo interno: ognuna di esse, infatti, rappresenta un oggetto che può essere inserito nella pagina. Per il momento c'è solo WebCustomControl1.

Figura 2. La Toolbox con il nuovo controllo Web
21b.gif

Aggiungiamo il nostro contollo alla pagina e, nella finestra delle proprietà, modifichiamo il valore di Text: a differenza di quanto avviene con i Web User Control, la modifica si riflette anche in fase di progettazione. Eseguiamo l'applicazione e verifichiamo il risultato nel browser.

Ora modifichiamo il controllo perchè il testo specificato appaia automaticamente in grassetto. Ricordando quanro detto in precedenza, è sufficiente modificare il codice HTML generato dal controllo, ovvero intervenire sul suo metodo Render().

Poichè il metodo Write() dell'oggetto HtmlTextWriter si limita a scrivere sulla pagina tutto quello che riceve come argomento, un primo modo per fare quello che vogliamo potrebbe essere inserire tutto in un'unica istruzione:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Questa soluzione è corretta, ma rischia di creare confusione, inoltre la possibilità di dimenticare qualche carattere <, > oppure / cresce all'aumentare del numero di tag da inserire.

Possiamo invece usare altri metodi messi a disposizione da HtmlTextWriter per produrre codice più leggibile e con una distinzione maggiore tra tag HTML e contenuto vero e proprio:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Il metodo WriteBeginTag() scrive il carattere < e il tag indicato come argomento, ma non lo chiude con > perchè, in generale, esso potrebbe contenere degli attributi (da specificare con il metodo WriteAttribute()). Per questo motivo è necessaria la successiva istruzione di Write(), che scrive semplicemente il carattere > (HtmlTextWriter.TagRightChar()).

In alternativa a queste due istruzioni, avremmo potuto usare semplicemente:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Dopo aver stampato il testo vero e proprio, chiudiamo il tag con il metodo WriteEndTag(). Ora ricompiliamo il controllo e visualizziamo il file "Default.aspx". Per osservare il nuovo comportamento dell'oggetto all'interno del Designer potrebbe essere necessario chiudere e riaprire la pagina.

Visualizzando il sorgente HTML della pagina nel browser, notiamo che il testo specificato nella proprietà Text del controllo è stato inserito tra i tag <b> e </b>.

È possibile scaricare tutto il codice che abbiamo realizzato cliccando .

Anche questi controlli, come i controlli Web utente, una volta inseriti in una pagina prevedono l'uso della clausola @ Register associata.

Continuiamo a parlare della Web Control Library e vediamo come creare controlli personalizzati estendendo gli oggetti esistenti.

Realizziamo il controllo che abbiamo creato con la tecnica Web User Control (Label+TextBox), costruendolo esclusivamente via codice. Questa soluzione ci permetterà di definire un controllo con layout dinamico, cosa che non è possibile fare utilizzando i Web User Control.

Riprendiamo la soluzione creata nella lezione precedente e aggiungiamo un nuovo Custom Control.

Clicchiamo col tasto destro del mouse sul nome del progetto «WebControlLibrary1» nel Solution Explorer e selezioniamo il comando Add quindi «New Item...» (Nuovo elemento).

Nella finestra di dialogo che appare è già selezionato l'elemento «Web Custom Control». Diamogli il nome «LabelTextBox» e clicchiamo su Add.

Figura 1. La finestra di dialogo Add New Item
22a.gif

Questa volta il codice di default di Visual Studio è superfluo per i nostri scopi: eliminiamo la proprietà «Text», la variabile privata «text» e il corpo del metodo Render().

Volendo realizzare una casella di testo con una caratteristica in più rispetto a quella predefinita, facciamo in modo che il nostro nuovo controllo estenda la classe TextBox invece del generico WebControl: così facendo, esso disporrà automaticamente di tutte le proprietà, i metodi e gli eventi della TextBox.
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Ora aggiungiamo una proprietà per impostare e recuperare l'etichetta associata alla casella di testo:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Notiamo l'uso del Custom Attribute «DefaultValue», con cui si specifica qual è il valore predefinito della proprietà (è buona norma che il valore predefinito di una proprietà sia uguale al suo valore iniziale).

Inseriamo anche una proprietà che consente di specificare se l'etichetta deve essere visualizzata a fianco oppure sopra la casella di testo: in questo modo il nostro controllo avrà un layout dinamico, ovvero un layout variabile a seconda dell'impostazione delle sue proprietà:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
La proprietà «CaptionPosition» può assumere i valori dell'enumerazione «CaptionPositions», utilizzata per determinarela posizione dell'etichetta:

Side, per mostrarla a fianco della casella di testo,
Over, perché sia inserita al di sopra della casella di testo.
Infine, nel metodo Render() scriviamo le istruzioni che producono il codice HTML per la visualizzazione del controllo:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
L'etichetta è visualizzata attraverso il tag <span> (prime tre istruzioni). Subito dopo, se si è deciso di visualizzare l'etichetta sopra la casella di testo (mCaptionPosition == CaptionPositions.Over), nella pagina viene inserito il tag <br />. L'ultima istruzione richiama il metodo Render() della classe base, ovvero TextBox, che si occupa di visualizzare la casella di testo vera e propria.

Compiliamo la Web Control Library e visualizziamo nel Designer la pagina «Default.aspx». Alla Toolbox è stato automaticamente aggiunto il nuovo controllo: clicchiamo due volte sulla voce LabelTextBox per inserirlo nella pagina.

Figura 2. Il nuovo controllo nella Toolbox
22b.gif

Le proprietà di cui dispone sono tutte quelle della classica TextBox, più le due che abbiamo definito.

Figura 3. Le nuove proprietà del controllo
22c.gif

Proviamo a modificare CaptionPosition: il suo cambiamento produce immediatamente un nuovo layout per il controllo.

Figura 4. I due layout del controllo
22d.gif

Ereditando da TextBox il nostro controllo espone tutti gli eventi tipici dell'oggetto base. Ad esempio, cliccando due volte su di esso, nel code behind sarà automaticamente aggiunto l'event handler per l'evento TextChanged.

Cliccare
Perfavore, Entra oppure Registrati per vedere i Link!
per scaricare il codice sorgente del controllo LabelTextBox insieme con una Web Form che ne mostra l'utilizzo.

I file di configurazione​
Il comportamento di un'applicazione ASP .NET può essere personalizzato mediante l'uso di opportuni file di configurazione, che hanno nome «Web.config» e sono scritti in formato XML.

È possibile avere un file «Web.config» diverso in ciascuna directory del sito: ognuno di essi applica le impostazioni di configurazione sulla propria directory e su tutte le sottodirectory.

I file di configurazione nelle sottodirectory possono stabilire configurazioni aggiuntive a quelle ereditate dalle directory padre oppure possono sostituire o modificare quelle definite nei livelli superiori.

Un file Web.config può contenere vari tipi di informazioni:

variabili comuni a tutte le pagine;
configurazioni per le sessioni;
opzioni per la gestione degli errori;
informazioni per la sicurezza.
Abbiamo già accennato al file Web.config in precedenza, quando lo abbiamo aggiunto al progetto per attivare il debug dell'applicazione.

Apriamo uno qualunque dei siti Web che abbiamo realizzato nelle scorse lezioni, cliccando due volte sul file Web.Config all'interno del Solution Explorer si aprirà un file contenente un gran numero di commenti, inseriti automaticamente allo scopo di facilitare la modifica delle opzioni.

In effetti, prima della versione 2.0 del Framework .NET, il file Web.config poteva essere modificato esclusivamente con un editor di testi; non esisteva alcuno strumento visuale di editing, per cui i commenti erano fondamentali.

ASP .NET 2.0, invece, fornisce anche uno strumento grafico per la configurazione che si basa su un'interfaccia Web ed è raggiungibile facendo cliccando su ASP .NET Configuration nel Solution Explorer.

Figura 1. ASP .NET Configuration
23a.gif

Il file Web.Config è composto da due sezioni fondamentali: appSettings e system.web:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
La sezione appSettings contiene le variabili che si vogliono condividere tra tutte le pagine dell'applicazione. Ad esempio:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Per recuperare i valori delle variabili Titolo ed Autore da una qualunque pagina contenuta nella stessa directory del file Web.config, o in una sua sottodirectory, si deve utilizzare la classe ConfigurationManager:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
La sezione system.web, invece, contiene le impostazioni proprie dell'applicazione. Nelle lezioni precedenti abbiamo aggiunto al progetto un file Web.config con debug attivo. A questa scelta corrisponde la seguente opzione in system.web:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Di conseguenza, se vogliamo disattivare il debug per il sito Web (ad esempio perché siamo in fase di pubblicazione), è sufficiente impostare tale proprietà su false. In questa sezione, inoltre, attraverso il tag <customErrors>, è possibile definire la pagina da richiamare in caso di errore:
Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Ogni volta che si verifica una situazione imprevista (pagina non trovata, accesso non autorizzato, ecc.), invece del messaggio di errore predefinito sarà visualizzata la pagina Error.htm.

Oltre a Web.config, ad un sito ASP .NET può essere aggiunto un file di nome global.asax. Esso risiede nella directory principale del sito ed è una sorta di "contenitore" di codice comune all'applicazione. Viene impiegato, tra l'altro, per:

eseguire operazioni all'avvio e al termine delle sessioni e dell'applicazione;
eseguire del codice al verificarsi di una condizione di errore.
Per inserire il file global.asax ad un progetto, nella finestra di dialogo «Add New Item» è necessario selezionare la voce Global Application Class. Il file che viene aggiunto include già le dichiarazioni per gli event handler che possono essere definiti.

I commenti inseriti automaticamente spiegano quando i vari eventi sono generati: ad esempio, al verificarsi di un errore, se questo non viene già intercettato dal codice presente nella pagina con un blocco try-catch, viene scatenato l'evento Application_Error.

Strumenti di sviluppo alternativi​
Tutti gli esempi che abbiamo realizzato in questo corso sono stati creati utilizzando Visual Studio, l'ambiente di sviluppo Microsoft.

Questo, tuttavia, non è l'unico strumento disponibile: tra le alternative, segnaliamo SharpDevelop: si tratta di un IDE per la realizzazione di applicazioni .NET completamente gratuito e distribuito con il codice sorgente.

Figura 1. L'ambiente di sviluppo di SharpDevelop
24a.gif

Scritto in C#, riproduce abbastanza fedelmente l'ambiente di sviluppo di Visual Studio .NET 2003 (pur non in tutte le funzionalità), supporta le versioni 1.0 e 1.1 del Framework .NET, può compilare utilizzando Mono (di cui parleremo tra breve) e consente di realizzare applicazioni in C#, Visual Basic .NET e C++.

Dispone anche di uno strumento per l'importazione/esportazione di progetti di Visual Studio e la traduzione di codice C# in VB .NET e viceversa.

Al momento della stesura di questa guida, inoltre, è in fase di realizzazione una nuova release di SharpDevelop, che sarà compatibile con la versione 2.0 del Framework e supporterà le nuove caratteristiche dell'editor di Visual Studio 2005.

Lo stesso Framework .NET di Microsoft ha una sua controparte: Mono, un'implementazione open source del Framework che ha come obiettivo primario quello di rendere multipiattaforma le applicazioni .NET.

Grazie a Mono è possibile scrivere applicazioni in C#, utilizzando le stesse tecniche che abbiamo analizzato in questa guida, ed eseguirle su piattaforma Linux o Windows.

Frutto di un intenso lavoro di sviluppo da parte di Ximian e di una nutrita comunità di sviluppatori di tutto il mondo, Mono si compone di:

un compilatore per i linguaggi C# e VB .NET con cui è possibile sviluppare applicazioni compatibili con la piattaforma di Microsoft;
un compilatore che consente a Linux di far girare applicazioni scritte sotto un qualsiasi altro sistema operativo che supporti .NET, primo fra tutti Windows;
un modulo che aggiunge ad Apache il supporto per ASP .NET;
un insieme di librerie che permette lo sviluppo di applicazioni utente e servizi Web in grado di girare sotto vari sistemi operativi.
Mono comprende anche l'ambiente di sviluppo MonoDevelop, una macchina virtuale Java ed il supporto a diversi altri linguaggi di script, tra cui Python e JScript.

Fra le maggiori lacune che attualmente si riscontrano c'è la mancanza del supporto a COM. In ogni caso, le versioni di Mono si susseguono in maniera costante.

Attualmente Mono fornisce un supporto quasi completo della «Base Class Library» di .NET ed integra alcuni dei nuovi controlli introdotti con ASP .NET 2.0.

Fonte= Programmazione.Html​
 
Inizialmente ho pensato:"Cacchio!In questo forum esiste qualcuno che studia il C# oltre a me!Fantastico!", poi ho visto "Fonte:HTML.it" e ho pensato: "Ma vaffanculo!***".
E' un po' troppo lunga e i colori non mi "garbano".

***Chiedo gentilmente ai mod di non eliminare la bestemmia perché non offende nessuno ed è ciò che penserebbe chiunque al posto mio :soso:
 
Inizialmente ho pensato:"Cacchio!In questo forum esiste qualcuno che studia il C# oltre a me!Fantastico!", poi ho visto "Fonte:HTML.it" e ho pensato: "Ma vaffanculo!***".
E' un po' troppo lunga e i colori non mi "garbano".

***Chiedo gentilmente ai mod di non eliminare la bestemmia perché non offende nessuno ed è ciò che penserebbe chiunque al posto mio :soso:
O_O Io conosco il C# Ma Questo non vuol dire che devo fare una guida!