Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Vb.net
1.
2. A1. Introduzione
Benvenuti, aspir anti pr ogr ammator i! In questa guida dalla lunghezza chiolemtr ica impar er ete cosa significa e cosa
compor ta pr ogr ammar e, e tutti i tr ucchi e gli espedienti per costr uir e solide e sicur e applicazioni.
Una veloc e panoramic a sulla programmazione
La pr ogr ammazione è quella disciplina dell'infor matica che si occupa di idear e, costr uir e e mantener e il softw ar e.
Queste sono le tr e pr incipali divisioni che si possono oper ar e all'inter no di questa speciale e affascinante br anca
dell'ingegner ia. Infatti, un buon pr ogr ammator e deve pr ima di tutto analizzar e il pr oblema, quindi pensar e a una
possibile soluzione, se esiste, e costr uir e mentalmente un'ipotetica str uttur a del softw ar e che dovr à impegnar si a
scr iver e: questa par te della pr ogettazione si chiama analisi. Successivamente, si viene alla fase più tecnica, e che
implica una conoscenza dir etta del linguaggio di pr ogr ammazione usato: in questa guida, mi occuper ò di descr iver e il
Visual Basic .NET. Una volta sviluppato il pr ogr amma, lo si deve testar e per tr ovar e eventuali malfunzionamenti (bugs)
- che, per inciso, si manifestano solo quando non dovr ebber o - e, come ultima oper azione, bisogna attuar e una
manutenzione per iodica dello stesso, od or ganizzar e un efficiente sistema di aggior namento. Inutile dir e che l'ultima
fase è necessar ia solo nel caso di gr andi applicazioni commer ciali e non cer tamente nel contesto di piccoli pr ogr ammi
amator iali.
Pr ima di iniziar e, una br eve sintesi di alcuni dettagli tecnici: i ter mini da conoscer e, e gli ambienti di sviluppo da
usar e.
Alc uni termini da c onosc ere
Co dice so r g ente o so r g ente: l'insieme di tutte le istr uzioni che il pr ogr ammator e scr ive e fa eseguir e al
pr ogr amma. Il file testuale che contiene tali istr uzioni viene esso stesso chiamato sor gente
Co m pilato r e: il softw ar e utilizzato per cr ear e il pr ogr amma finito (un eseguibile *.ex e) a par tir e dal solo codice
sor gente
Debug g er : il softw ar e usato per l'analisi e la r isoluzione degli er r or i (bugs) all'inter no di un pr ogr amma;
Par o le r iser v ate o k eyw o r ds: di solito vengono evidenziate dai compilator i in un color e diver so e sono par ole
pr edefinite intr inseche del linguaggio, che ser vono per scopi ben pr ecisi.
Ambiente di sviluppo
L'ambiente di sviluppo che pr ender ò come r ifer imento per questa guida è Visual Basic Ex pr ess 2008 (scar icabile dal
Sito Ufficiale della M icr o so ft; se si ha un pr ofilo Passpor t.NET è possibile r egistr ar e il pr odotto e ottener e una
ver sione completa). Potete comunque scar icar e Shar pDevelop da qui (vedi sezione dow nloads), un pr ogr amma gr atis e
molto buono (tr over ete una r ecensione nella sezione Sofw tar e di Pier oTofy.it r edatta da me e HeDo qui). Dato che le
ver sioni pr ecedenti della guida, dalle quali è r ipr esa la maggior anza dei sor genti pr oposti, sono state r edatte
pr endendo come esempio Visual Basic Ex pr ess 2005, potete scar icar e anche quello da qui.
3. A2. Classi, Moduli e Namespace
Objec t Oriented Programming
I linguaggi .NET sono orien tati agli oggetti e così lo è anche VB.NET. Questo appr occio alla pr ogr ammazione ha avuto
molto successo negli ultimi anni e si basa fondamentalmente sui concetti di astr azione, oggetto e inter azione fr a
oggetti. A lor o volta, questi ultimi costituiscono un potente str umento per la modellizzazione e un nuovo modo di
avvicinar si alla r isoluzione dei pr oblemi. La par ticolar e mentalità che questa linea di sviluppo adotta è favor evole alla
r appr esentazione dei dati in modo ger ar chico, e per questo motivo il suo par adig m a di pr ogr ammazione - ossia
l'insieme degli str umenti concettuali messi a disposizione dal linguaggio e il modo in cui il pr ogr ammator e concepisce
l'applicativo - è definito da tr e concetti car dine: l'er editar ietà, il po lim o r fism o e l'incapsulam ento . Molto pr esto
ar r iver emo ad osser var e nel par ticolar e le car atter istiche di ognuno di essi, ma pr ima vediamo di iniziar e con
l'intr odur r e l'entità fondamentale che si pone alla base di tutti questi str umenti: la classe.
Le Classi
Come dicevo, una car atter istica par ticolar e di questa categor ia di linguaggi è che essi sono basati su un unico
impor tantissimo concetto fondamentale: gli o g g etti, i quali vengono r appr esentati da classi. Una classe non è altr o che
la r appr esentazio ne - o v v iam ente astr atta - di qualco sa di co ncr eto , mentr e l'oggetto sar à una concr etizzazione
di questa r appr esentazione (per una discussione più appr ofondita sulla differ enza tr a classe e oggetto, veder e capitolo
A7). Ad esempio, in un pr ogr amma che deve gestir e una videoteca, ogni videocassetta o DVD è r appr esentato da una
classe; in un pr ogr amma per la fattur azione dei clienti, ogni cliente e ogni fattur a vengono r appr esentati da una
classe. Insomma, ogni cosa, ogni entità, ogni r elazione - per fino ogni er r or e - tr ova la sua r appr esentazione in una
classe.
Detto questo, viene spontaneo pensar e che, se ogni cosa è astr atta da una classe, questa classe dovr à anche contener e
dei dati su quella cosa. Ad esempio, la classe Utente dovr à contener e infor mazioni sul nome dell'utente, sulla sua
passw or d, sulla sua data di nascita e su molto altr o su cui si può sor volar e. Si dice che tutte queste infor mazioni sono
espo ste dalla classe: ognuna di esse, inoltr e, è r appr esentata da quello che viene chiamato m em br o. I membr i di una
classe sono tutti quei dati e quelle funzionalità che essa espone.
Per esser e usabile, per ò, una classe deve venir e pr ima dichiar ata, mediante un pr eciso codice. L'atto di dichiar ar e una
qualsiasi entità le per mette di iniziar e ad "esister e": il pr ogr ammator e deve infatti ser vir si di qualcosa che è già stato
definito da qualche par te, e senza di quello non può costr uir e niente. Con la par ola "entità" mi r ifer isco a qualsiasi cosa
si possa usar e in pr ogr ammazione: dato che le vostr e conoscenze sono limitate, non posso che usar e dei ter mini
gener ici e piuttosto vaghi, ma in br eve il mio lessico si far à più pr eciso. Nella pr atica, una classe si dichiar a così:
1. Class [NomeClasse]
2. ...
3. End Class
dove [NomeClasse] è un qualsiasi nome che potete decider e ar bitr ar iamente, a seconda di cosa debba esser e
r appr esentato. Tutto il codice compr eso tr a le par ole sopr a citate è inter no alla classe e si chiama co r po ; tutte le
entità esistenti nel cor po sono dei membr i. Ad esempio, se si volesse idealizzar e a livello di codice un tr iangolo, si
scr iver ebbe questo:
1. Class Triangolo
2. ...
3. End Class
Nel cor po di Tr iangolo si potr anno poi definir e tutte le infor mazioni che gli si possono attr ibuir e, come la lunghezza
4. dei lati, la tipologia, l'ampiezza degli angoli, ecceter a...
I Moduli
Nonostante il nome, i moduli non sono niente altr o che dei tipi speciali di classi. La differ enza sostanziale tr a i due
ter mini ver r à chiar ita molto più avanti nella guida, poiché le vostr e attuali competenze non sono sufficienti a un
completo appr endimento. Tuttavia, i moduli sar anno la tipologia di classe più usata in tutta la sezione A.
I Namespac e
Possiamo definir e classi e moduli come un ità fun zion ali: essi r appr esentano qualcosa, possono esser e usate,
manipolate, istanziate, dichiar ate, ecceter a... Sono quindi str umenti attivi di pr ogr ammazione, che ser vono a
r ealizzar e concr etamente azioni e a pr odur r e r isultati. I namespace, invece, appar tengono a tutt'altr o gener e di
categor ia: essi sono solo dei r aggr uppamenti "passivi" di classi o di moduli. Possiamo pensar e a un namespace come ad
una car tella, entr o la quale possono star e files, ma anche altr e car telle, ognuna delle quali r aggr uppa un par ticolar e
tipo di infor mazione. Ad esempio, volendo scr iver e un pr ogr amma che aiuti nel calcolo geometr ico di alcune figur e, si
potr ebbe usar e un codice str uttur ate come segue:
01. Namespace Triangoli
02. Class Scaleno
03. '...
04. End Class
05.
06. Class Isoscele
07. '...
08. End Class
09.
10. Class Equilatero
11. '...
12. End Class
13. End Namespace
14.
15. Namespace Quadrilateri
16. Namespace Parallelogrammi
17. Class Parallelogramma
18. '...
19. End Class
20.
21. Namespace Rombi
22. Class Rombo
23. '...
24. End Class
25.
26. Class Quadrato
27. '...
28. End Class
29. End Namespace
30. End Namespace
31. End Namespace
Come si vede, tutte le classi che r appr esentano tipologie di tr iangoli (Scaleno, Isoscele, Equilater o) sono all'inter no del
namespace Tr iangoli; allo stesso modo esiste anche il namespace Quadr ilater i, che contiene al suo inter no un altr o
namespace Par allelogr ammi, poiché tutti i par allelogr ammi sono quadr ilater i, per definizione. In quest'ultimo esiste la
classe Par allelogr amma che r appr esenta una gener ica figur a di questo tipo, ma esiste ancor a un altr o namespace
Rombi: come noto, infatti, tutti i r ombi sono anche par allelogr ammi.
Dall'esempio si osser va che i namespace categor izzano le unità funzionali, dividendole in insiemi di per tinenza. Quando
un namespace si tr ova all'inter no di un altr o namespace, lo si definisce nidificato: in questo caso, Par alleloogr ammi e
Rombi sono namespace nidificati. Altr a cosa: al contr ar io della classi, gli spazi di nomi (italianizzazione dell'inglese
name-space) non possiedono un "cor po", poiché questo ter mine si può usar e solo quando si par la di qualcosa di attivo;
5. per lo stesso motivo, non si può neanche par lar e di membr i di un namespace.
6. A3. Panoramica sul Framework .NET
Come ho spiegato nel pr ecedente capitolo, il concetto più impor tante della pr ogr ammazione ad oggetti è la classe.
Quindi, per scr iver e i nostr i pr ogr ammi, utilizzer emo sempr e, bene o male, queste entità. Ma non è possibile pensar e
che si debba scr iver e tutto da zer o: per i pr ogr ammator i .NET, esiste un vastissimo inventar io di classi già pr onte,
r aggr uppate sotto una tr entina di namespace fondamentali. L'insieme di tutti questi str umenti di pr ogr ammazione è il
Fr am ew o r k .NET, l'ossatur a pr incipale su cui si r eggono tutti i linguaggi basati sulla tecnologia .NET (di cui Vb.NET è
solo un esponente, accanto al più usato C# e agli altr i meno noti, come J#, F#, Delphi per .NET, ecceter a...). Sar ebbe
tuttavia r iduttivo descr iver e tale piattafor ma come un semplice agglomer ato di libr er ie (vedi oltr e), quando essa
contempla meccanismi assai più complessi, che sovr intendono alla gener ale esecuzione di tutte le applicazioni .NET.
L'inter a str uttur a del Fr amew or k si pr esente come str atificata in diver si livelli:
1. Sistema operativo
Il Fr amew or k .NET pr esenta una str uttur a str atificata, alla base della quale r isiede il sistema oper ativo, Window s. Più
pr ecisamente, si consider a il sistema oper ativo e l'API (Application Pr ogr amming Inter face) di Window s, che espone
tutti i metodi r esi disponibili al pr ogr ammator e per svolger e un dato compito.
2. Common Language Runtime
Un gr adino più in su c'è il Common Language Runtime (CLR), r esponsabile dei ser vizi basilar i del Fr amew or k, quali la
gestione della memor ia e la sua liber azione tr amite il meccanismo di Gar bage Collection (vedi capitolo r elativo), la
gestione str uttur ata delle eccezioni (er r or i) e il multithr eading. Nessuna applicazione inter agisce mai dir ettamente
con il CLR, ma tutte sono allo stesso modo contr ollate da esso, come se fosse il lor o super visor e. Pr opr io per questo si
definisce il codice .NET M an aged o Safe ("Gestito" o "Sicur o"), poichè questo str ato del Fr amew or k gar antisce che non
vengano mai eseguite istr uzioni dannose che possano mandar e in cr ash il pr ogr amma o il sistema oper ativo stesso. Al
contr ar io, il codice Unmanaged o Unsafe può eseguir e oper azioni r ischiose per il computer : sor genti pr odotti in Vb6 o
C++ possono pr odur r e tale tipo di codice.
3. Base Class Library
Lo str ato successivo è denominato Base Class Libr ar y (BCL): questa par te contiene tutti i tipi e le classi disponibili nel
Fr amew or k (il che cor r isponde in numer o a diver se migliaia di elementi), r aggr uppati in una tr entina di file pr incipali
(assembly). In questi ultimi è compr esa la definizione della classe System.Object, dalla quale der iva pr essochè ogni altr a
classe. I dati contenuti nella BCL per mettono di svolger e ogni oper azione possibile sulla macchina.
4. X ML
Successivamente tr oviamo i dati, le r isor se. Per salvar e i dati viene usato quasi sempr e il for mato XM L (eXtensible
Mar kup Language), che utilizza dei tag spesso nidificati per contener e i campi necessar i. La str uttur a di questo tipo di
file, inoltr e, è adatta alla r appr esentazione ger ar chica, un metodo che nell'ambiente .net è impor tantissimo. I file di
configur azione e quelli delle opzioni impostate dell'utente, ad esempio, vengono salvati in for mato XML. Anche la nuova
tecnologia denominata Window s Pr esentation Foundation (WPF), intr odotta nella ver sione 3.5 del Fr amew or k, che
per mette di cr ear e contr olli dalla gr afica accattivante e str avagante, si basa su un linguaggio di contr assegno (di
mar kup) sur r ogato dell'XML.
7. 5. W indow s Forms e ASP.NET
Al livello super ior e tr oviamo ASP.NET e Window s For ms, ossia le inter facce gr afiche che r icopr ono il codice
dell'applicazione ver a e pr opr ia. La pr ima è una tecnologia pensata per lo sviluppo sul Web, mentr e la seconda for nisce
sostanzialmente la possibilità di cr ear e una inter faccia gr afica (Gr aphical User Inter face, GUI) in tutto e per tutto
uguale a quella classica, a finestr e, dei sistemi oper ativi Window s. La costr uzione di una Window s For m (ossia una
singola finestr a) è semplice e avviene come nel Vb classico, e chi sta leggendo questa guida per passar e dal VB6 al
VB.NET lo sapr à bene: si pr endono uno o più contr olli e li si tr ascinano sulla super ficie della finestr a, dopodichè si scr ive
il codice associato ad ognuno dei lor o eventi.
6. Common Language Spec ific ations
Il penultimo stadio della str atificazione del Fr amew or k coincide con le Common Language Specifications (CLS), ossia un
insieme di specifiche che definiscono i r equisiti minimi r ichiesti a un linguaggio di pr ogr ammazione per esser e
qualificato come .NET. Un esempio di tali dir ettive: il linguaggio deve saper e gestir e tipi base come str inghe e numer i
inter i, vettor i e collezioni a base zer o e deve saper pr ocessar e un'eccezione scatenata dal Fr amew or k.
7. Linguaggi .NET
In cima alla str uttur a ci sono tutti i linguaggi .net: Vb, C#, J#, ecceter a.
V ersioni del Framew ork
Con il passar e degli anni, a par tir e dal 2002, Micr osoft ha r ilasciato ver sioni successive del Fr amew or k .NET e ognuna
di queste r elease ha intr odotto nuovi concetti di pr ogr ammazione e nuove possibilità per lo sviluppator e.
Par allelamente all'uscita di queste nuove ver sioni, sono state cr eate anche edizioni successive del linguaggio VB.NET,
ognuna delle quali è stata natur almente accostata alla ver sione del Fr amew or k su cui si r eggeva. Ecco una r apida
panor amica dell'evoluzione del linguaggio:
VB2002: si basa sulla ver sione 1.0 del Fr amew or k
VB2003: si basa sulla ver sione 1.1 del Fr amew or k
VB2005: si basa sulla ver sione 2.0 del Fr amew or k. Questa è la ver sione maggior mente utilizzata in questa
guida, sebbene cer ti capitoli si concentr er anno sull'intr oduzione di alcuni nuovi aspetti por tati da VB2008
VB2008: si basa sulla ver sione 3.5 del Fr amew or k. La ver sione 3.0 si fondava ancor a sulla 2.0 del CLR e per ciò le
modifiche consistevano sostanzialmente nell'aggiunta di alcuni componenti e nell'appor to di diver se miglior ie e
cor r ezioni
VB2010: si basa sulla ver sione 4.0 del Fr amew or k
8. A4. Utilizzo base dell'IDE
IDE? Me lo sono dimentic ato a c asa...
Non vi pr eoccupate: se avete seguito tutti i capitoli fino a questo punto, siete già un possesso di un IDE: Visual Basic
2005 (o 2008) Ex pr ess. L'acr onimo IDE significa Integr ated Development Envir onment ("ambiente di sviluppo integr ato")
ed indica un softw ar e che aiuta il pr ogr ammator e nella stesur a del codice. Il softw ar e che vi ho consigliato for nisce,
sebbene sia la ver sione fr ee, un numer o molto alto di str umenti e tools. In pr imis, contiene, ovviamente, un editor di
codice sor gente, pr ogettato in modo da evidenziar e in modo differ ente le keyw or ds e da suppor tar e molte funzioni di
r icer ca e r aggr uppamento che vedr emo in seguito. Accanto a questo, i pr incipali componenti che non possono mancar e
in un IDE sono il compilator e ed il debugger , di cui ho dato una veloce definizione nel capitolo intr oduttivo. Il pr imo ha
lo scopo di legger e il sor gente scr itto dal pr ogr ammator e e pr odur r e da questo un eseguibile: i passi che vengono
por tati a ter mine dur ante un pr ocesso di compilazione sono in r ealtà più di uno (di solito compilazion e e lin kin g), ma
molto spesso si semplifica il tutto par lando semplicemente di compilazione. Il secondo, invece, è il pr ogr amma che vi
dar à più filo da tor cer e, anche se in r ealtà sar à il vostr o miglior e aiutante (diciamo che vi sfinir à a fin di bene): il
debugger ha la funzione di analizzar e e segnalar e i bugs (bachi, er r or i) che si ver ificano dur ante l'esecuzione; assieme
ad un r appor to dettagliato del tipo di er r or e ver ificatosi, segnala par allelamente anche il punto del codice che ha dato
pr oblemi, in modo da r ender e molto più semplice individuar e e cor r egger e la falla.
Funzionamento del c ompilatore .NET
Il compilator e è, come già detto, quel softw ar e necessar io a "tr asfor mar e" il codice sor gente scr itto in un deter minato
linguaggio in un pr ogr amma eseguibile. Nor malmente, un compilator e pr odur r ebbe un applicativo tr aducendo le
istr uzioni testuali intr odotte dal pr ogr ammator e in linguaggio macchina, ossia una ser ie di bit univocamente
inter pr etabile dal pr ocessor e. I compilator i .NET, invece, hanno un compor tamento differ ente, in quanto il lor o output
non è un "nor male pr ogr amma" scr itto in linguaggio macchina, ma si tr atta di una ser ie di istr uzioni codificate in un
altr o linguaggio speciale, chiamato IL (Inter mediate Language). Come sugger isce il nome, esso si tr ova ad un livello
inter medio tr a la macchina e l'astr azione: è super ior e r ispetto al pur o codice binar io, ma allo stesso tempo è un
gr adino più sotto r ispetto ai linguaggi .NET. Venendo a conoscenza di queste infor mazioni, dovr ebbe sor ger e
spontaneamente una domanda: come fa allor a un pr ogr amma .NET ad esser e eseguito? La r isposta è semplice: è lo
stesso Fr amew or k che si occupa di inter pr etar ne le istr uzioni e di eseguir le, sempr e sotto la super visione del CLR. Per
questo motivo, si hanno tr e impor tanti conseguenze:
Non è possibile far cor r er e un'applicazione .NET su una macchina spr ovvista del Fr amew or k;
Il codice .NET è sempr e sicur o;
Un pr ogr amma .NET è sempr e disassemblabile: su questo punto mi soffer mer ò in seguito.
Creare una Console A pplic ation
Nei pr ossimi capitoli inizer ò ad intr odur r e la sintassi del linguaggio, ossia le r egole da r ispettar e quando si scr ive un
codice. Per tutti gli esempi della sezione A, far ò uso di applicazioni conso le (avete pr esente la finestr ella con lo sfondo
ner o?), che lavor ano in DOS. Per cr ear e una Applicazione Console bisogna selezionar e dal menù File del compilator e, la
voce New Pr oject, e quindi sceglier e il tipo di applicazione desider ata. Dopodichè, il compilator e scr iver à
aumaticamente alcune r ighe di codice pr eimpostate, che possono esser e simili a queste:
Module Module1
9. Sub Main()
End Sub
End Module
Nello scr eenshot pr oposto qui sopr a si possono veder e le tr e ar ee in cui è solitamente divisa l'inter faccia del
compilator e: non vi pr eoccupate se la vostr a appar e differ ente, poiché, essendo modificabile a piacimento, la mia
potr ebbe esser e diver sa dal layout pr eimpostato del compilator e. Per or a, le finestr e impor tanti sono due: quella del
codice, dove andr emo a scr iver e le istr uzioni, e quella degli er r or i, dove potr ete tener e costantemente sott'occhio se
avete commesso degli er r or i di sintassi. Nello scr eenshot la seconda di queste non è visibile, ma la si può por tar e in
pr imo piano tenendo pr emuto Ctr l e digitando in successione "" ed "E".
Per quanto r iguar da il codice che appar e, ho già specificato in pr ecedenza che i moduli sono dei tipi speciali di classe, e
fin qui vi baster à saper e questo. Quello che potr este non conoscer e è la par te di sor gente in cui appaiono le par ole Sub
ed End Sub: anche in questo caso, la tr attazione par ticolar e di queste keyw or ds sar à r imandata più in là. Per or a
possiamo consider ar e la Sub Main() come il pr ogr amma inter o: ogni cosa che viene scr itta tr a "Sub Main()" ed "End Sub"
ver r à eseguita quando si pr emer à il pulsante Star t (il tr iangolino ver de in alto sulla bar r a degli str umenti), o in
alter nativa F5.
Compilazione del programma finito
Una volta finito di scr iver e il codice e di testar lo usando le funzioni dell'IDE (ivi compr esa l'esecuzione in modalità debug
pr emendo F5), sar à necessar io cr ear e il pr ogr amma finito. Quello che avete eseguito fin'or a non er a altr o che una
ver sione più lenta e meno ottimizzata del softw ar e scr itto, poiché c'er a bisogno di contr ollar e tutti gli er r or i e i bugs,
impiegando tempo e spazio per memor izzar e le infor mazioni r elative al debug, appunto. Per cr ear e l'applicazione
r eale finita, è necessar io compilar e il codice in modalità r elease. Apr ite la scheda delle pr opr ietà di pr ogetto, dal menù
pr incipale Pr oject > [NomePr ogetto] Pr oper ties (l'ultima voce del sottomenù); selezionate la scheda Compile e cambiate
il campo Configur ation su Release, quindi pr emete Build > Build Pr oject (Build è sempr e una voce del menù pr incipale).
10. Tr over ete l'eseguibile compilato nella car tella DocumentiVisual Studio 2008Pr ojects[Nome pr ogetto]binRelease.
11. A5. Variabili e costanti
Le variabili
Una var iabile è uno spazio di memor ia RAM (Random Access Memor y) in cui vengono allocati dei dati dal pr ogr amma, ed
è possibile modificar ne od ottener ne il valor e facendo r ifer imento ad un nome che si definisce ar bitr ar iamente. Questo
nome si dice anche iden tificatore (o, più r ar amente, mn emon ico), e può esser e costituito da un qualunque insieme di
car atter i alfanumer ici e under scor e: l'unica condizione da r ispettar e per cr ear e un nome valido è che questo non può
iniziar e con un numer o. Per esempio "Pippo", "_Pluto", "Mar io78" o anche "_12345" sono identificator i validi, mentr e
"0Luigi" non lo è. Il pr incipale scopo di una var iabile è contener e dati utili al pr ogr amma; tali dati possono r isieder e in
memor ia per un tempo più o meno lungo, a seconda di quando una var iabile viene cr eata o distr utta: ogni var iabile,
comunque, cessa di esister e nel momento in cui il pr ogr amma viene chiuso. Essa, inoltr e, può contener e una
gr andissima var ità di tipi di dato diver si: dai numer i alle str inghe (testo), dalle date ai valor i booleani, per allar gar si
poi a tipi più ampi, in gr ado di r appr esentar e un inter o file. Ma pr ima di ar r ivar e a spiegar e tutto questo, bisogna
analizzar e in che modo si dichiar a una var iabile. La dichiar azione, tanto di una costante quanto di una classe, è l'atto
definitivo con cui si stabilisce l'esistenza di un'entità e la si r ende disponibile o accessibile alle altr i par ti del
pr ogr amma. Ogni cosa, per esser e usata, deve pr ima esser e dichiar ata da qualche par te: questa oper azione equivale,
ad esempio, a definir e un concetto in matematica: la definizione è impor tantissima.
Ecco un semplice esempio:
01. Module Module1
02. Sub Main()
03. Dim Ciao As Int16
04. Ciao = 78
05. Ciao = Ciao + 2
06. Console.WriteLine(Ciao)
07. Console.Readkey()
08. End Sub
09. End Module
Facendo cor r er e il pr ogr amma avr emo una scher mata ner a su cui viene visualizzato il numer o 80. Per chè? Or a
vediamo.
Come avr ete notato, le var iabili si dichiar ano in un modo specifico, usando le keyw or ds Dim e A s:
1. Dim [nome] As [tipo]
Dove [nome] è l'identificator e con cui ci si r ifer isce ad una var iabile e [tipo] il tipo di dato contenuto nella var iabile.
Esistono molteplici tipi di var iabile fr a cui è possibile sceglier e. Ecco un elenco dei tipi base (che sono consider ati
keyw or ds):
Byte: inter o a 8 bit che può assumer e valor i da 0 a 255;
Char : valor e a 8 bit che può assumer e i valor i di ogni car atter e della tastier a (compr esi quelli speciali);
Int16 o Sho r t: inter o a 16 bit che può assumer e valor i da -32768 a +32767;
Int32 o Integ er : inter o a 32 bit da -2147483648 a +2147483647;
Int64 o Lo ng : inter o a 64 bit da cir ca -922000000000000000 a +9220000000000000000;
Sing le: decimale da cir ca -3,4e+38 a +3,4e+38, con un inter vallo minimo di cir ca 1,4e-45;
Do uble: decimale da cir ca -1,79e+308 a +1,79e+308, con un inter vallo minimo di cir ca 4,9e-324;
Bo o lean: dato a 4 bytes che può assumer e due valor i, Tr ue (ver o) e False (falso). Nonostante la limitatezza del
suo campo di azione, che concettualmente potr ebbe r estr inger si ad un solo bit, il tipo Boolean occupa 32bit di
memor ia: sono quindi da evitar e gr andi quantità di questo tipo;
Str ing : valor e di minimo 10 bytes, composto da una sequenza di car atter i. Se vogliamo, possiamo assimilar lo ad
12. un testo;
Object: r appr esenta un qualsiasi tipo (ma non è un tipo base).
I tipi base vengono detti anche ato m ici o pr im itiv i, poiché non possono esser e ulter ior mente scomposti. Esistono,
quindi, anche tipi der iv ati, appar tenenti a svar iate tipologie che analizzer emo in seguito, fr a cui si annover ano anche
le classi: ogni tipo der ivato è scomponibile in un insieme di tipi base.
Or a, quindi, possiamo estr apolar e delle infor mazioni in più dal codice pr oposto: dato che segue la keyw or d Dim, "Ciao"
è l'identificator e di una var iabile di tipo Int16 (infatti dopo As è stato specificato pr opr io Int16). Questo significa che
"Ciao" può contener e solo numer i inter i che, in valor e assoluto, non super ino 32767. Ovviamente, la scelta di un tipo di
dato piuttosto che un altr o var ia in funzione del compito che si intende svolger e: maggior e è la pr ecisione e l'or dine di
gr andezza dei valor i coinvolti e maggior e sar à anche l'uso di memor ia che si dovr à sostener e. Continuando a legger e,
si incontr a, nella r iga successiva, un'assegnazione, ossia una oper azione che pone nella var iabile un cer to valor e, in
questo caso 78; l'assegnazione avviene mediante l'uso dell'oper ator e uguale "=". L'istr uzione successiva è simile a questa,
ma con una sostanziale differ enza: il valor e assegnato alla var iabile è influenzato dalla var iabile stessa. Nell'esempio
pr oposto, il codice:
1. Ciao = Ciao + 2
ha la funzione di incr ementar e di due unità il contenuto di Ciao. Questa istr uzione potr ebbe sembr ar e algebr icamente
scor r etta, ma bisogna r icor dar e che si tr atta di un comando (e non di un'equazione): pr ima di scr iver e nella cella di
memor ia associata alla var iabile il numer o che il pr ogr ammator e ha designato, il pr ogr amma r isolve l'espr essione a
destr a dell'uguale sostituendo ad ogni var iabile il suo valor e, e ottenendo, quindi, 78 + 2 = 80. Le ultime due r ighe,
invece, fanno visualizzar e a scher mo il contenuto di Ciao e fer mano il pr ogr amma, in attesa della pr essione di un
pulsante.
Come si è visto dall'esempio pr ecedente, con le var iabili di tipo numer ico si possono eseguir e oper azioni ar itmetiche.
Gli oper ator i messi a disposizione dal Fr amew or k sono:
+ : addizione;
- : sottr azione;
* : pr odotto;
/ : divisione;
: divisione tr a inter i (r estituisce come r isultato un numer o inter o a pr escinder e dal tipo degli oper andi, che
possono anche esser e decimali);
Mod : r estituisce il r esto di una divisione inter a;
= : assegna alla var iabile posta a sinistr a dell'uguale il valor e posto dopo l'uguale;
& : concatena una str inga con un numer o o una str inga con un'altr a str inga.
01. Module Module1
02. Sub Main()
03. 'Interi
04. Dim Intero, Ese As Int16
05. 'Decimale
06. Dim Decimale As Single
07. 'Booleano
08. Dim Vero As Boolean
09. 'Stringa
10. Dim Frase As String
11.
12. Intero = 90
13. Ese = Intero * 2 / 68
14. Intero = Ese - Intero * Intero
15. Decimale = 90.76
16. Decimale = Ese / Intero
17. Vero = True
18. Frase = "Ciao."
19. 'L'operatore "+" tra stringhe concatena due stringhe. Dopo la
20.
13. 'prossima istruzione, la variabile Frase conterrà:
21. ' "Buon giornoCiao"
22. Frase = "Buon giorno" + "Ciao"
23. 'L'operatore "&" può concatenare qualsiasi dato e
24. 'restituisce una stringa. Dopo la prossima istruzione, la
25. 'variabile Frase conterrà:
26. ' "Il valore decimale è: -0,0003705076"
27. Frase = "Il valore decimale è: " & Decimale
28. End Sub
29. End Module
Esistono poi degli speciali oper ator i di assegnamento, che velocizzano l'assegnazione di valor i, alcuni sono:
01. Module Module1
02. Sub Main()
03. Dim V, B As Int32
04.
05. V += B 'Equivale a V = V + B
06. B -= V 'Equivale a B = B - V
07. V *= B 'Equivale a V = V * B
08. B /= V 'Equivale a B = B / V
09. End Sub
10. End Module
Le fr asi poste dopo un apice (') sono dette co m m enti e ser vono per spiegar e cosa viene scr itto nel codice. Il contenuto
di un commento NON influisce in nessun modo su ciò che è scr itto nel sor gente, ma ha una funzione ESCLUSIVAMENTE
esplicativa.
Le c ostanti
Abbiamo visto che il valor e delle var iabili può esser e modificato a piacimento. Ebbene quello delle costanti, come il
nome sugger isce, no. Esistono per semplificar e le oper azioni. Per esempio, invece di digitar e 3,1415926535897932 per
il Pi g r eco , è possibile dichiar ar e una costante di nome Pi che abbia quel valor e ed utilizzar la nelle espr essioni. La
sintassi per dichiar ar e una costante è la seguente:
1. Const [nome] As [tipo] = [valore]
Ci sono due lampanti differ enze r ispetto al codice usato per dichiar ar e una var iabile. La pr ima è, ovviamente, l'uso
della keyw or d Con s t al posto di Dim; la seconda consiste nell'assegnazione posta subito dopo la dichiar azione. Infatti,
una costante, per esser e tale, dev e contener e qualcosa: per questo motivo è o bblig ato r io specificar e sempr e, dopo
la dichiar azione, il valor e che la costante assumer à. Questo valor e non potr à mai esser e modificato.
Esempio:
01. Module Module1
02. Sub Main()
03. Const Pi As Single = 3.1415926535897932
04. Dim Raggio, Area As Double
05.
06. 'Questa istruzione scrive sul monitor il messaggio posto tra
07. 'virgolette nelle parentesi
08. Console.WriteLine("Inserire il raggio di un cerchio:")
09.
10. 'Questa istruzione leggè un valore immesso dalla tastiera e
11. 'lo deposita nella variabile Raggio
12. Raggio = Console.ReadLine
13. Area = Raggio * Raggio * Pi
14.
15. Console.WriteLine("L'Area è: " & Area)
16.
17. 'Questa istruzione ferma il programma in attesa della pressione
18. 'di un pulsante
19. Console.ReadKey()
20. End Sub
21. End Module
14. N.B.: a causa della lor o stessa natur a, le costanti NON possono esser e inizializzate con un valor e che dipenda da una
funzione. Scr ivo questo appunto per pur a utilità di consultazione: anche se or a potr à non r isultar e chiar o, vi capiter à
più avanti di imbatter vi in er r or i del gener e:
1. Const Sqrt2 As Single = Math.Sqrt(2)
Sqr t2 dovr ebbe esser e una costante numer ica decimale che contiene la r adice quadr ata di due. Sebbene il codice
sembr i cor r etto, il compilator e segnaler à come er r or e l'espr essione Math.Sqr t(2), poiché essa è una funzione, mentr e
dopo l'uguale è r ichiesto un valor e sempr e costante. Il codice cor r etto è
1. Const Sqrt2 As Single = 1.4142135
Le istruzioni
Tutti i comandi che abbiamo impar tito al computer e che abbiamo gener icamente chiamato con il nome di istr uzioni
(come Console.Wr iteLine()) hanno dei nomi più specifici: sono pr o cedur e o funzio ni, in sostanza sottopr ogr ammi già
scr itti. Pr ocedur e e funzioni possono esser e globalmente indicate con la par ola m eto do . I metodi accettano dei
par am etr i passatigli tr a par entesi: se i par ametr i sono di più di uno vengono separ ati da vir gole. I par ametr i
ser vono per comunicar e al metodo i dati sui quali questo dovr à lavor ar e. La differ enza tr a una pr ocedur a e una
funzione r isiede nel fatto che la pr ima fa semplicemente eseguir e istr uzioni al computer , mentr e la seconda r estituise
un valor e. Ad esempio:
01. Module Module1
02. Sub Main()
03. Dim F As Double
04.
05. 'Questa è una funzione che restituisce la radice quadrata di 56
06. F = Math.Sqrt(56)
07.
08. 'Questa è una procedura che scrive a video un messaggio
09. Console.WriteLine("La radice di 56 è " & F)
10. Console.ReadKey()
11. End Sub
12. End Module
Anche i metodi ver r anno tr attai successivamente in dettaglio.
15. A6. Tipi Reference e tipi Value
Tutti i tipi di var iabile che possono esser e cr eati si r aggr uppano sotto due gr andi categor ie: Refer ence e Value. I pr imi
si compor tano come oggetti, mentr e i secondi r appr esentano tipi scalar i o numer ici, ma vediamo di metter e un po'
or dine in tutti questi concetti.
P.S.: per una miglior e compr esione di questo capitolo, consiglio solo a chi ha già esper ienza nel campo della
pr ogr ammazione (in qualsiasi altr o linguaggio) di legger e questo ar tico lo sull'utilizzo della memor ia da par te di un
pr ogr amma.
Differenza tra Classi e Oggetti
All'inizio della guida mi sono soffer mato ad elogiar e le classi e la lor o enor me impor tanza nell'ambiente .NET.
Successivamente ho fatto menzione al tipo System.Object e al fatto che ogni cosa sia un oggetto. La differ enza tr a
o g g etto e classe è di vitale impor tanza per capir e come vanno le cose nell'ambito della pr ogr ammazione OO. Una
classe r appr esenta l'astr azione di qualcosa di concr eto; un oggetto, invece, è qualcosa di concr eto e viene
r appr esentato da una classe. Per far e un esempio banale, sappiamo benissimo che esiste il concetto di "uomo", ma ogni
individuo sul pianeta, pur mantenendo alcune car atter istiche simili e costanti, è differ ente r ispetto agli altr i. Facendo
un par allelismo con la pr ogr ammazione, quindi, il singolo individuo, ad esempio io stesso, è un oggetto, mentr e il
gener ale concetto di "uomo" che ognuno di noi conosce è la classe. Se qualcuno dei lettor i ha studiato filosofia,
r iconoscer à in questa differ enza la stessa che Platone identificava nella discr epanza tr a mondo sensibile e Iper ur anio.
Avendo ben chiar i questi concetti, si può or a intr odur r e un po' di ger go tecnico. Ogni oggetto è anche detto istanza
della classe che lo r appr esenta (voi siete istanze della classe Uomo XD) e is tan ziare un oggetto significa cr ear lo.
1. 'New serve per creare fisicamente degli oggetti in memoria
2. Dim O1 As New Object
3. Dim O2 As New Object
O1 e O2 sono entr ambe istanze della classe Object, ma sono diver si fr a di lor o: in comune hanno solo l'appar tenenza allo
stesso tipo.
N.B.: come si è notato, "tipo" e "classe" sono ter mini spesso equivalenti, ma non gener alizzate questa associazione.
Tipi Referenc e
Ogni cosa nel Fr amew or k è un oggetto e la maggior par te di essi sono tipi r efer ence. Si dicono tipi r efer ence tutti
quei tipi che der ivano dir ettamente dalla classe System.Object (la "der ivazione" appar tiene a un concetto che spiegher ò
più avanti): questa classe è dichiar ata all'inter no di una libr er ia della Base Class Libr ar y, ossia l'ar chivio di classi del
Fr amew or k. Nel capitolo pr ecedente si è visto come sia possibile assegnar e un valor e ad una var iabile utilizzando
l'oper ator e uguale "=". Con questo meccanismo, un deter minato valor e viene depositato nella casella di memor ia che la
var iabile occupa. Ebbene, facendo uso dei tipi r efer ence, questo non avviene. Quando si utilizza l'uguale per assegnar e
un valor e a tali var iabili, quello che effettivamente viene r iposto nella lor o par te di memor ia è un puntator e inter o a
32bit (su sistemi oper ativi a 32bit). Per chi non lo sapesse, un puntator e è una speciale var iabile che, invece di
contener e un pr opr io valor e, contiene l'indir izzo di un'ar ea di memor ia contenente altr i dati. Il puntator e viene
memor izzato come al solito sullo stack , mentr e il ver o oggetto viene cr eato e deposto in un'ar ea di memor ia
differ ente, detta heap m anag ed, dove esiste sotto la super visione del CLR. Quando una var iabile di questo tipo viene
impostata a Nothing (una costante che vedr emo tr a poco), la par te dell'heap managed che l'oggetto occupa viene
r ilasciata dur ante il pr ocesso di g ar bag e co llectio n ("r accolta dei r ifiuti"). Tuttavia, ciò non avviene subito, poichè il
meccanismo del Fr amew or k fa in modo di avviar e la gar bage collection solo quando è necessar io, quindi quando la
16. memor ia comincia a scar seggiar e: supponendo che un pr ogr amma abbia r elativamente pochi oggetti, questi
potr ebber o "viver e" indistur bati fino alla fine del pr ogr amma anche dopo esser e stati lo g icam ente distr utti, il che
significa che è stato eliminato manualmente qualsiasi r ifer imento ad essi (vedi par agr afo successivo). Data
l'impossibilità di deter minar e a pr ior i quando un oggetto ver r à distr utto, si ha un fenomeno che va sotto il nome di
finalizzazio ne no n deter m inistica (il ter mine "finalizzazione" non è casule: veder e il capitolo sui distr uttor i per
maggior i infor mazioni).
Nothing
Nothing è una costante di tipo r efer ence che r appr esenta l'assenza di un oggetto piuttosto che un oggetto nullo. Infatti,
por r e una var iabile oggetto uguale a Nothing equivale a distr ugger la logicamente.
1. Dim O As New Object 'L'oggetto viene creato
2. O = Nothing 'L'oggetto viene logicamente distrutto
La distr uzione logica non coincide con la distr uzione fisica dell'oggetto (ossia la sua r imzione dalla memor ia), poiché,
come detto pr ima, il pr ocesso di liber azione della memor ia viene avviato solo quando è necessar io. Non è possibile
assegnar e Nothing a un tipo value, ma è possibile usar e speciali tipi value che suppor tano tale valor e: per ulter ior i
dettagli, veder e "Tipi Nullable".
Tipi V alue
Ogni tipo v alue der iva dalla classe System.ValueType, che der iva a sua volta da System.Object, ma ne r idefinisce i
metodi. Ogni var iabile di questo tipo contiene effettivamente il pr opr io valor e e non un puntator e ad esso. Inoltr e,
esse hanno dei vantaggi in ter mini di memor ia e velocità: occupano in gener e meno spazio; data la lor o posizione sullo
stack non vi è bisogno di r efer enziar e un puntator e per ottener e o impostar ne i valor i (r efer enziar e un puntator e
significa r ecar si all'indir izzo di memor ia puntato e legger ne il contenuto); non c'è necessità di occupar e spazio nello
heap managed: se la var iabile viene distr utta, cessa di esister e all'istante e non si deve attuar e nessuna oper azione di
r ilascio delle r isor se. Notar e che non è possibile distr ugger e logicamente una var iabile value, fatta eccezione per cer ti
tipi der ivati.
Is e =
Nel lavor ar e con tipi r efer ence e value bisogna pr estar e molta attenzione a quando si utilizzano gli oper ator i di
assegnamento. Come già detto, i r efer ence contengono un puntator e, per ciò se si scr ive questo codice:
1. Dim O1, O2 As Object
2. '...
3. O1 = O2
quello che O2 conter r à non sar à un valor e identico a O1, ma un puntator e alla stessa ar ea di memor ia di O1. Questo
pr ovoca un fatto str ano, poichè sia O1 che O2 puntano alla stessa ar ea di memor ia: quindi O1 e O2 so no lo stesso
o g g etto , soltanto r ifer ito con nomi difer si. In casi simili, si può utilizzar e l'oper ator e Is per ver ificar e che due
var iabili puntino allo stesso oggetto:
1. 'Scrive a schermo se è vero oppure no che
2. 'O1 e O2 sono lo stesso oggetto
3. Console.WriteLine(O1 Is O2)
La scr itta che appar ir à sullo scher mo sar à "Tr ue", ossia "Ver o". Utilizzar e Is per compar ar e un oggetto a Nothing
equivale a ver ificar e che tale oggetto sia stato distr utto.
Questo NON avviene per i tipi value: quando ad un tipo value si assegna un altr o valor e con l'oper ator e =, si passa
17. effettivamente una co pia del valor e. Non è possibile utilizzar e Is con i tipi value poichè Is è definito solo per i
r efer ence.
Boxing e Unboxing
Consider iamo il seguente codice:
1. Dim I As Int32 = 50
2. Dim O As Object
3. O = I
I è un tipo value, mentr e O è un tipo r efer ence. Quello che succede dietr o le quinte è semplice: il .NET cr ea un nuovo
oggetto, per ciò un tipo r efer ence, con il r ispettivo puntator e, e quindi gli assegna il valor e di I: quando il pr ocesso è
finito assegna il puntator e al nuovo oggetto a O. Questa conver sione spr eca tempo e spazio nello heap managed e viene
definita come bo xing . L'oper azione inver sa è l'unboxing e consiste nell'assegnar e un tipo r efer ence a un tipo value. Le
oper azioni che si svolgono sono le stesse, ma al contr ar io: entr ambe spr ecano tempo e cpu, quindi sono da evitar e se
non str ettamente necessar ie. Quando si può sceglier e, quindi, sono meglio di tipi value.
Una pr ecisazione: in tutti i pr ossimi capitoli capiter à fr equentemente che io dica cose del tipo "la var iabile X è un
oggetto di tipo Str ing" oppur e "le due var iabili sono lo stesso oggetto". Si tr atta solo di una via più br eve per evitar e il
for malismo tecnico, poiché, se una var iabile è dichiar ata di tipo r efer ence, essa è pr opr iamente un riferimen to
all'oggetto e non un oggetto. Gli oggetti "vivono" indistur bati nell'heap managed, quel magico posto che nessuno conosce:
noi possiamo solo usar e r ifer imenti a tali oggetti, ossia possiamo solo indicar li ("eccolo là! guar da! l'hai visto? ma sì,
pr opr io là! non lo vedi?").
18. A7. Il costrutto If
Capita spessissimo di dover eseguir e un contr ollo per ver ificar e se vigono cer te condizioni. È possibile attuar e tale
oper azione tr amite un co str utto di co ntr o llo , la cui for ma più comune e diffusa è il costr utto If. Questo per mette di
contr ollar e se una condizione è ver a. Ad esempio: in un pr ogr amma che calcoli l'ar ea di un quadr ato si deve impor r e di
visualizzar e un messaggio di er r or e nel caso l'utente immetta una misur a negativa, poichè, come è noto, non esistono
lati la cui misur a è un numer o negativo:
01. Module Module1
02. Sub Main()
03. Dim Lato As Single
04.
05. Console.WriteLine("Inserire il lato di un quadrato:")
06. Lato = Console.ReadLine
07.
08. If Lato < 0 Then 'Se Lato è minore di 0...
09. Console.WriteLine("Il lato non può avere una misura negativa!")
10. Else 'Altrimenti, se non lo è...
11. Console.WriteLine("L'area del quadrato è: " & Lato * Lato)
12. End If 'Fine controllo
13.
14. Console.ReadKey()
15. End Sub
16. End Module
Come sicur amente avr ete intuito, questo contr ollo si può associar e al costr utto italiano "Se avviene qualcosa Allor a fai
questo Altr imenti fai quell'altr o". Si può eseguir e qualsiasi tipo di compar azione tr a If e Then utilizzando i seguenti
oper ator i di confr onto:
> : maggior e
< : minor e
= : uguaglianza
<> : diver so
>= : maggior e o uguale
<= : minor e o uguale
Is : identicità (solo per tipi r efer ence)
IsNot : negazione di Is (solo per tipi r efer ence)
Ma l'impor tante è r icor dar si di attener si a questa sintassi:
1. If [Condizione] Then
2. [istruzioni]
3. Else
4. [istruzioni alternative]
5. End If
If nidific ati
Quando si tr ova un costr utto If all'inter no di un altr o costr utto If, si dice che si tr atta di un Co str utto If Nidificato .
Questo avviene abbastanza spesso, specie se si ha bisogno di far e contr olli multipli:
01. Module Module1
02. Sub Main()
03. Dim Numero As Int16
04.
05.
19. Console.WriteLine("Inserisci un numero:")
06. Numero = Console.ReadLine
07.
08. If Numero > 0 Then
09. If Numero < 5 Then
10. Console.WriteLine("Hai indovnato il numero!")
11. End If
12. Else
13. Console.WriteLine("Numero errato!")
14. End If
15.
16. Console.ReadKey()
17. End Sub
18. End Module
Se il numer o inser ito da tastier a è compr eso fr a 0 e 5, estr emi esclusi, allor a l'utente ha indovinato il numer o,
altr imenti no. Si può tr ovar e un numer o illimitato di If nidificati, ma è meglio limitar ne l'uso e, piuttosto, far e utilizzo
di co nnettiv i lo g ici.
I c onnettivi logic i
I connettivi logici sono 4: And, Or , Xor e Not. Ser vono per costr uir e contr olli complessi. Di seguito un'illustr azione del
lor o funzionamento:
If A And B : la condizione r isulta ver ificata se sia A che B sono ver e co ntem po r aneam e nte
If A Or B : la condizione r isulta ver ificata se è ver a alm eno una delle due condizioni
If A Xor B: la condizione r isulta ver a se una so la delle due condizioni è ver a
If Not A: la condizione r isulta ver ificata se è falsa
Un esempio pr atico:
01. Module Module1
02. Sub Main()
03. Dim a, b As Double
04.
05. Console.WriteLine("Inserire i lati di un rettangolo:")
06. a = Console.ReadLine
07. b = Console.ReadLine
08.
09. 'Se tutti e due i lati sono maggiori di 0
10. If a > 0 And b > 0 Then
11. Console.WriteLine("L'area è: " & a * b)
12. Else
13. Console.WriteLine("Non esistono lati con misure negative!")
14. End If
15. Console.Readkey()
16. End Sub
17. End Module
Continuare il c ontrollo: ElseIf
Nei pr ecedenti esempi, la seconda par te del costr utto è sempr e stata Els e, una par ola r iser vata che indica cosa far e se
n on si ver ifica la condizione pr oposta dalla pr ima par te. Il suo valor e è, quindi, di pur a alter nativa. Esiste, tuttavia,
una var iante di Else che consente di continuar e con un altr o contr ollo senza dover r icor r er e ad If nidificati (a cui è
sempr e meglio supplir e con qualcosa di più or dinato). Ammettiamo, ad esempio, di aver e un codice 'autocr itico' simile:
01. Module Module1
02. Sub Main()
03. Dim Voto As Single
04.
05. Console.WriteLine("Inserisci il tuo voto:")
06.
20. Voto = Console.ReadLine
07.
08. If Voto < 3 Then
09. Console.WriteLine("Sei senza speranze!")
10. Else
11. If Voto < 5 Then
12. Console.WriteLine("Ancora un piccolo sforzo...")
13. Else
14. If Voto < 7 Then
15. Console.WriteLine("Stai andando discretamente")
16. Else
17. If Voto < 9 Then
18. Console.WriteLine("Molto bene, continua così")
19. Else
20. Console.WriteLine("Sei praticamente perfetto!")
21. End If
22. End If
23. End If
24. End If
25.
26. Console.ReadKey()
27. End Sub
28. End Module
E' abbastanza disor dinato... La var iante ElseIf è molto utile per miglior e la leggibilità del codice:
01. Module Module1
02. Sub Main()
03. Dim Voto As Single
04.
05. Console.WriteLine("Inserisci il tuo voto:")
06. Voto = Console.ReadLine
07.
08. If Voto < 3 Then
09. Console.WriteLine("Sei senza speranze!")
10. ElseIf Voto < 5 Then
11. Console.WriteLine("Ancora un piccolo sforzo...")
12. ElseIf Voto < 7 Then
13. Console.WriteLine("Stai andando discretamente")
14. ElseIf Voto < 9 Then
15. Console.WriteLine("Molto bene, continua così")
16. Else
17. Console.WriteLine("Sei praticamente perfetto!")
18. End If
19.
20. Console.ReadKey()
21. End Sub
22. End Module
Notate che tutti gli ElseIf fanno par te dello s tes s o costr utto: mentr e nell'esempio ogni If nidificato er a un blocco a sé
stante, dotato infatti di un pr opr io End If, in questo caso ogni alter nativa-selettiva fa comunque par te dell'unico If
iniziale, pr otr atto solamente un poco più a lungo.
Bloc c hi di istruzioni
Fino a questo punto, gli esempi pr oposti non hanno mai dichiar ato una var iabile dentr o un costr utto If, ma solo
all'inizio del pr ogr amma, dopo Sub Main(). È possibile dichiar ar e var iabili in altr i punti del codice che non siano all'inizio
della Sub? Cer tamente sì. A differ enza di altr i, i linguaggi .NET per mettono di dichiar ar e var iabili in qualunque punto
del sor gente, dove occor r e, evitando un gigantesco agglomer ato di dichiar azioni iniziali, for temente disper sive per chi
legge. Questo è un gr ande vantaggio, ma bisogna far e attenzione ai blocchi di codice. Con questo ter mine ci si r ifer isce
a par ti del sor gente compr ese tr a due par ole r iser vate, che in VB di solito sono accoppiate in questo modo:
1. [Keyword]
2. 'Blocco di codice
3. End [Keyword]
21. Ad esempio, tutto il codice compr eso tr a Sub ed End Sub costituisce un blocco, così come lo costituisce quello compr eso
tr a If ed End If (se non vi è un Else), tr a If ed Else o addir ttur a tr a Module ed End Module. Facendo questa distinzione
sar à facile intuir e che una var iabile dichiar ata in un blocco no n è v isibile al di fuor i di esso. Con questo voglio dir e
che la sua dichiar azione vale solo all'inter no di quel blocco. Ecco una dimostr azione:
01. Module Module1
02. Sub Main()
03. 'a, b e c fanno parte del blocco delimitato da Sub ...
04. 'End Sub
05. Dim a, b, c As Single
06.
07. 'Semplice esempio di risoluzione di equazione di
08. 'secondo grado
09. Console.WriteLine("Equazione: ax2 + bx + c = 0")
10. Console.WriteLine("Inserisci, in ordine, a, b e c:")
11. a = Console.ReadLine
12. b = Console.ReadLine
13. c = Console.ReadLine
14.
15. If a = 0 Then
16. Console.WriteLine("L'equazione si abbassa di grado")
17. Console.ReadKey()
18. 'Con Exit Sub si esce dalla Sub, che in questo caso
19. 'coincide con il programma. Equivale a terminare
20. 'il programma stesso
21. Exit Sub
22. End If
23.
24. 'Anche delta fa parte del blocco delimitato da Sub ...
25. 'End Sub
26. Dim delta As Single = b ^ 2 - 4 * a * c
27.
28. 'Esistono due soluzioni distinte
29. If delta > 0 Then
30. 'Queste variabili fanno parte del blocco di If ...
31. 'ElseIf
32. Dim x1, x2 As Single
33. 'È possibile accedere senza problemi alla variabile
34. 'delta, poiché questo blocco è a sua volta
35. 'all'interno del blocco in cui è dichiarato delta
36. x1 = (-b + Math.Sqrt(delta)) / (2 * a)
37. x2 = (-b - Math.Sqrt(delta)) / (2 * a)
38. Console.WriteLine("Soluzioni: ")
39. Console.WriteLine("x1 = " & x1)
40. Console.WriteLine("x2 = " & x2)
41.
42. 'Esiste una soluzione doppia
43. ElseIf delta = 0 Then
44. 'Questa variabile fa parte del blocco ElseIf ... Else
45. Dim x As Single
46. x = -b / (2 * a)
47. Console.WriteLine("Soluzione doppia: ")
48. Console.WriteLine("x = " & x)
49.
50. 'Non esistono soluzioni in R
51. Else
52. Console.WriteLine("Non esistono soluzioni in R")
53. End If
54.
55. Console.ReadKey()
56. End Sub
57. End Module
Se in questo codice, pr ima del Console.ReadKey(), finale pr ovassimo a usar e una fr a le var iabili x , x 1 o x 2, otter r emmo
un er r or e:
22. Questo succede per chè nessuna var iabile dichiar ata all'inter no di un blocco è accessibile al di fuor i di esso. Con questo
schemino r udimentale sar à più facile capir e:
Le fr ecce ver di indicano che un codice può acceder e a cer te var iabili, mentr e quelle r osse indicano che non vi può
acceder e. Come salta subito agli occhi, sono per messe tutte le r ichieste che vanno dall'inter no di un blocco ver so
l'ester no, mentr e sono pr oibite tutte quelle che vanno dall'ester no ver so l'inter no. Questa r egola vale sempr e, in
qualsiasi cir costanza e per qualsiasi tipo di blocco: non ci sono eccezioni.
23. A8. Il costrutto Select Case
Abbiamo visto nel capitolo pr ecedente come si possa far pr ocessar e al computer un contr ollo per ver ificar e cer te
condizioni. Supponiamo, or a, di aver e 20 contr olli di uguaglianza del tipo:
01. '...
02. If A = 1 Then
03. 'istruzioni
04. End If
05. If A = 2 Then
06. 'istruzioni
07. End If
08. If A = 3 Then
09. 'istruzioni
10. End If
11. 'eccetera
In questo caso il costr utto If diventa non solo noioso, ma anche ingombr ante e disor dinato. Per eseguir e questo tipo di
contr olli multipli esiste un costr utto apposito, Select Case, che ha questa sintassi:
01. '...
02. Select Case [Nome variabile da analizzare]
03. Case [valore1]
04. 'istruzioni
05. Case [valore2]
06. 'istruzioni
07. Case [valore3]
08. 'istruzioni
09. End Select
Questo tipo di contr ollo r ende molto più linear e, semplice e veloce il codice sor gente. Un esempio:
01. Module Module 1
02. Sub Main()
03. Dim a, b As Double
04. Dim C As Byte
05.
06. Console.WriteLine("Inserire due numeri: ")
07. a = Console.ReadLine
08. b = Console.ReadLine
09. Console.WriteLine("Inserire 1 per calcolare la somma, 2 per la differenza, 3 per il
prodotto, 4 per il quoziente:")
10. C = Console.ReadLine
11.
12. Select Case C
13. Case 1
14. Console.WriteLine(a + b)
15. Case 2
16. Console.WriteLine(a - b)
17. Case 3
18. Console.WriteLine(a * b)
19. Case 4
20. Console.WriteLine(a / b)
21. End Select
22.
23. Console.ReadKey()
24. End Sub
25. End Module
Molto semplice, ma anche molto efficace, specialmente utile nei pr ogr ammi in cui bisogna consider ar e par ecchi valor i.
Anche se nell'esempio ho utilizzato solamente numer i, è possibile consider ar e var iabili di qualsiasi tipo, sia base
(str inghe, date), sia der ivato (str uttur e, classi). Ad esempio:
1.
24. Dim S As String
2. '...
3. Select Case S
4. Case "ciao"
5. '...
6. Case "buongiorno"
7. '...
8. End Select
V arianti del c ostrutto
Anche in questo caso, esistono numer ose var ianti, che per mettono non solo di ver ificar e uguaglianze come nei casi
pr ecedenti, ma anche di contr ollar e disuguaglianze e analizzar e insiemi di valor i. Ecco una lista delle possibilità:
Uso della v ir g o la
La vir gola per mette di definir e non solo uno, ma molti valor i possibili in un solo Case. Ad esempio:
01. Dim A As Int32
02. '...
03. Select Case A
04. Case 1, 2, 3
05. 'Questo codice viene eseguito solo se A
06. 'contiene un valore pari a 1, 2 o 3
07. Case 4, 6, 9
08. 'Questo codice viene eseguito solo se A
09. 'contiene un valore pari a 4, 6 o 9
10. End Select
Il codice sopr a pr oposto con Select equivale ad un If scr itto come segue:
1. If A = 1 Or A = 2 Or A = 3 Then
2. '...
3. ElseIf A = 4 Or A = 6 Or A = 9 Then
4. '...
5. End If
Uso di To
Al contr ar io, la keyw or d To per mette di definir e un ran ge di valor i, ossia un inter vallo di valor i, per il quale la
condizione r isulta ver ificata se la var iabile in analisi r icade in tale inter vallo.
1. Select Case A
2. Case 67 To 90
3. 'Questo codice viene eseguito solo se A
4. 'contiene un valore compreso tra 67 e 90 (estremi inclusi)
5. Case 91 To 191
6. 'Questo codice viene eseguito solo se A
7. 'contiene un valore compreso tra 91 e 191
8. End Select
Questo cor r isponde ad un If scr itto come segue:
1. If A >= 67 And A <= 90 Then
2. '...
3. ElseIf A >= 91 And A <= 191 Then
4. '...
5. End If
Uso di Is
Is è usato in questo contesto per ver ificar e delle condizioni facendo uso di nor mali oper ator i di confr onto
(meggior e, minor e, diver so, ecceter a...). L'Is usato nel costr utto Select Case non ha assolutamente niente a che
veder e con quello usato per ver ificar e l'identicità di due oggetti: ha lo stesso nome, ma la funzione è
completamente differ ente.
01.
25. Select Case A
02. Case Is >= 6
03. 'Questo codice viene eseguito solo se A
04. 'contiene un valore maggiore o uguale di 6
05. Case Is > 1
06. 'Questo codice viene eseguito solo se A
07. 'contiene un valore maggiore di 1 (e minore di 6,
08. 'dato che, se si è arrivati a questo Case,
09. 'significa che la condizione del Case precedente non
10. 'è stata soddisfatta)
11. End Select
Il suo equivalente If:
1. If A >= 6 Then
2. '...
3. ElseIf A > 1 Then
4. '...
5. End If
Uso di Else
Anche nel Select è lecito usar e Else: il Case che include questa istr uzione è solitamente l'ultimo di tutte le
alter native possibili e pr escr ive di eseguir e il codice che segue solo se tutte le altr e condizioni non sono state
soddisfatte:
01. Select Case A
02. Case 1, 4
03. 'Questo codice viene eseguito solo se A
04. 'contiene 1 o 4
05. Case 9 To 12
06. 'Questo codice viene eseguito solo se A
07. 'contiene un valore compreso tra 9 e 12
08. Case Else
09. 'Questo codice viene eseguito solo se A
10. 'contiene un valore minore di 9 o maggiore di 12,
11. 'ma diverso da 1 e 4
12. End Select
Uso delle pr ecedenti alter nativ e in co m binazione
Tutti i modi illustr ati fino ad or a possono esser e uniti in un solo Case per ottener e potenti condizioni di
contr ollo:
1. Select Case A
2. Case 7, 9, 10 To 15, Is >= 90
3. 'Questo codice viene eseguito solo se A
4. 'contiene 7 o 9 o un valore compreso tra 10 e 15
5. 'oppure un valore maggiore o uguale di 90
6. Case Else
7. '...
8. End Select
26. A9. I costrutti iterativi: Do Loop
Abbiamo visto che esistono costr utti per ver ificar e condizioni, o anche per ver ificar e in modo semplice e veloce molte
ugualiglianze. Or a vedr emo i cicli o costr utti iter ativi (dal latino iter , itiner is = "viaggio", ma anche "per la seconda
volta"). Essi hanno il compito di r ipeter e un blocco di istr uzioni un numer o deter minato o indeter minato di volte. Il
pr imo che analizzer emo è, appunto, il costr utto Do Loop, di cui esistono molte var ianti. La più semplice è ha questa
sintassi:
1. Do
2. 'istruzioni
3. Loop
Il suo compito consiste nel r ipete delle istr uzioni compr ese tr a Do e Loop un numer o infinito di volte: l'unico modo per
uscir e dal ciclo è usar e una speciale istr uzione: "Ex it Do", la quale ha la capacità di inter r omper e il ciclo all'istante ed
uscir e da esso. Questa semplice var iante viene usata in un numer o r idotto di casi, che si possono r icondur r e
sostanzialmente a due: quando si lavor a con la gr afica e le libr er ie Dir ectX, per disegnar e a scher mo i costanti
cambiamenti del mondo 2D o 3D; quando è necessar io ver ificar e le condizioni di uscita dal ciclo all'inter no del suo blocco
di codice. Ecco un esempio di questo secondo caso:
01. Module Module1
02.
03. Sub Main()
04. Dim a, b As Single
05.
06. Do
07. 'Pulisce lo schermo
08. Console.Clear()
09. 'L'underscore serve per andare a capo nel codice
10. Console.WriteLine("Inserire le misure di base e altezza " & _
11. "di un rettangolo:")
12. a = Console.ReadLine
13. b = Console.ReadLine
14.
15. 'Controlla che a e b non siano nulli. In quel caso, esce
16. 'dal ciclo. Se non ci fosse questo If in mezzo al codice,
17. 'verrebbe scritto a schermo il messaggio:
18. ' "L'area del rettangolo è: 0"
19. 'cosa che noi vogliamo evitare. Se si usasse un'altra
20. 'variante di Do Loop, questo succederebbe sempre. Ecco
21. 'perchè, in questa situazione, è meglio
22. 'servirsi del semplice Do Loop
23. If a = 0 Or b = 0 Then
24. Exit Do
25. End If
26.
27. Console.WriteLine("L'area del rettangolo è: " & (a * b))
28. Console.ReadKey()
29. Loop
30. End Sub
31.
32. End Module
Le altr e ver sioni del costr utto, invece, sono le seguenti:
1. Do
2. 'istruzioni
3. Loop While [condizione]
Esegue le istr uzioni specificate fintanto che una condizione r imane valida, ma tutte le istr uzioni vengono
eseguite almeno una volta, poichè While si tr ova dopo Do. Esempio:
27. 01. Module Module1
02. Sub Main()
03. Dim a As Int32 = 0
04.
05. Do
06. a += 1
07. Loop While (a < 2) And (a > 0)
08. Console.WriteLine(a)
09.
10. Console.ReadKey()
11. End Sub
12. End Module
Il codice scr iver à a scher mo "2".
1. Do While [condizione]
2. 'istruzioni
3. Loop
Esegue le istr uzioni specificate fintanto che una condizione r imane valida, ma se la condizione non è valida
all'inizio, non viene eseguita nessuna istr uzione nel blocco. Esempio:
01. Module Module1
02. Sub Main()
03. Dim a As Int32 = 0
04.
05. Do While (a < 2) And (a > 0)
06. a += 1
07. Loop
08. Console.WriteLine(a)
09.
10. Console.ReadKey()
11. End Sub
12. End Module
Il codice scr iver à a scher mo "0". Bisogna notar e come le stesse condizioni del caso pr ecedente, spostate da dopo
Loop a dopo Do, cambino il r isultato di tutto l'algor itmo. In questo caso, il codice nel ciclo non viene neppur e
eseguito per chè la condizione nel While diventa subito falsa (in quanto a = 0, e la pr oposizione "a < 0" r isulta
falsa). Nel caso pr ecedente, invece, il blocco veniva eseguito almeno una volta poiché la condizione di contr ollo si
tr ovava dopo di esso: in quel caso, a er a or mai stato incr ementato di 1 e per ciò soddisfaceva la condizione
affinché il ciclo continuasse (fino ad ar r ivar e ad a = 2, che er a il r isultato visualizzato).
1. Do
2. 'istruzioni
3. Loop Until [condizione]
Esegue le istr uzioni specificate fino a che non viene ver ificata la condizione, ma tutte le istr uzioni vengono
eseguite almeno una volta, poichè Until si tr ova dopo Do. Esempio:
01. Module Module1
02. Sub Main()
03. Dim a As Int32 = 0
04.
05. Do
06. a += 1
07. Loop Until (a <> 1)
08. Console.WriteLine(a)
09.
10. Console.ReadKey()
11. End Sub
12. End Module
A scher mo appar ir à "2".
1. Do Until [condizione]
2. 'istruzioni
3.
28. Loop
Esegue le istr uzioni specificate fino a che non viene soddisfatta la condizione, ma se la condizione è valida
all'inizio, non viene eseguita nessuna istr uzione del blocco. Esempio:
01. Module Module1
02. Sub Main()
03. Dim a As Int32 = 0
04.
05. Do Until (a <> 1)
06. a += 1
07. Loop
08. Console.WriteLine(a)
09.
10. Console.ReadKey()
11. End Sub
12. End Module
A scher mo appar ir à "0".
Un piccolo esempio finale:
01. Module Module1
02. Sub Main()
03. Dim a, b, c As Int32
04. Dim n As Int32
05.
06. Console.WriteLine("-- Successione di Fibonacci --")
07. Console.WriteLine("Inserire un numero oltre il quale terminare:")
08. n = Console.ReadLine
09.
10. If n = 0 Then
11. Console.WriteLine("Nessun numero della successione")
12. Console.ReadKey()
13. Exit Sub
14. End If
15.
16. a = 1
17. b = 1
18. Console.WriteLine(a)
19. Console.WriteLine(b)
20. Do While c < n
21. c = a + b
22. b = a
23. a = c
24. Console.WriteLine(c)
25. Loop
26.
27. Console.ReadKey()
28. End Sub
29. End Module
Suggerimen to
Per impostar e il valor e di Default (ossia il valor e pr edefinito) di una var iabile si può usar e questa sintassi:
1. Dim [nome] As [tipo] = [valore]
Funziona solo per una var iabile alla volta. Questo tipo di istr uzione si chiama in izializzazion e in -lin e.
29. A10. I costrutti iterativi: For
Dopo aver visto costr utti iter ativi che eseguono un ciclo un numer o indeter minato di volte, è ar r ivato il momento di
analizzar ne uno che, al contr ar io, esegue un deter minato numer o di iter azioni. La sintassi è la seguente:
1. Dim I As Int32
2.
3. For I = 0 To [numero]
4. 'istruzioni
5. Next
La var iabile I, usata in questo esempio, viene definita co ntator e e, ad ogni step, ossia ogni volta che il blocco di
istr uzioni si r ipete, viene automaticamente incr ementata di 1, sicchè la si può usar e all'inter no delle istr uzioni come
un ver o e pr opr io indice, per r ender e conto del punto al quale l'iter azione del For è ar r ivata. Bisogna far notar e che il
tipo usato per la var iabile contator e non deve sempr e esser e Int32, ma può var iar e, spaziando tr a la vasta gamma di
numer i inter i, con segno e senza segno, fino anche ai numer i decimali. Un esempio:
01. Module Module1
02. Sub Main()
03. Dim a As Int32
04.
05. 'Scrive 46 volte (da 0 a 45, 0 compreso, sono 46 numeri)
06. 'a schermo 'ciao'
07. For a = 0 To 45
08. Console.WriteLine("ciao")
09. Next
10.
11. Console.ReadKey()
12. End Sub
13. End Module
Ovviamente il valor e di par tenza r imane del tutto ar bitr ar io e può esser e deciso ed inizializzato ad un qualsiasi
valor e:
01. Module Module1
02. Sub Main()
03. Dim a, b As Int32
04.
05. Console.WriteLine("Inserisci un numero pari")
06. b = Console.ReadLine
07.
08. 'Se b non è pari, ossia se il resto della divisione
09. 'b/2 è diverso da 0
10. If b Mod 2 <> 0 Then
11. 'Lo fa diventare un numero pari, aggiungendo 1
12. b += 1
13. End If
14.
15. 'Scrive tutti i numeri da b a b+20
16. For a = b To b + 20
17. Console.WriteLine(a)
18. Next
19.
20. Console.ReadKey()
21. End Sub
22. End Module
Intr oduciamo or a una piccola var iante del pr ogr amma pr ecedente, nella quale si devono scr iver e solo i numer i par i da
b a b+20. Esistono due modi per r ealizzar e quanto detto. Il pr imo è abbastanza intuitivo, ma meno r affinato, e
consiste nel contr ollar e ad ogni iter azione la par ità del contator e:
1.
30. For a = b To b + 20
2. If a Mod 2 = 0 Then
3. Console.WriteLine(a)
4. End If
5. Next
Il secondo, invece, è più elegante e usa una ver sione "ar r icchita" della str uttur a iter ativa For , nella quale viene
specificato che l'incr emento del contator e non deve più esser e 1, ma bensì 2:
1. For a = b To b + 20 Step 2
2. Console.WriteLine(a)
3. Next
Infatti, la par ola r iser vata Step posta dopo il numer o a cui ar r ivar e (in questo caso b+20) indica di quanto deve esser e
aumentata la var iabile contator e del ciclo (in questo caso a) ad ogni step. L'incr emento può esser e un valor e inter o,
decimale, positivo o negativo, ma, cosa impor tante, deve sempr e appar tener e al r aggio d'azione del tipo del
contator e: ed esempio, non si può dichiar ar e una var iabile contator e di tipo Byte e un incr emento di -1, poichè Byte
compr ende solo numer i positivi (invece è possibile far lo con SByte, che va da -127 a 128). Allo stesso modo non si
dovr ebber o specificar e incr ementi decimali con contator i inter i.
Suggerimen to
Se non si vuole cr ear e una var iabile apposta per esser e contator e di un ciclo for , si può inzializzar e dir ettamente una
var iabile al suo inter no in questo modo:
1. For [variabile] As [tipo] = [valore] To [numero]
2. 'istruzioni
3. Next
4. 'Che, se volessimo descrivere con un esempio, diverrebbe così:
5. For H As Int16 = 78 To 108
6. 'istruzioni
7. Next
31. A11. Gli Array - Parte I
Array a una dimensione
Fino a questo momento abbiamo avuto a che far e con var iabili "singole". Con questo voglio dir e che ogni identificator e
dichiar ato puntava ad una cella di memor ia dove er a contenuto un solo valor e, leggibile e modificabile usando il nome
specificato nella dichiar azione della var iabile. L'esempio classico che si fa in questo contesto è quello della scatola, dove
una var iabile viene, appunto, assimilata ad una scatola, il cui contenuto può esser e pr eso, modificato e r eimmesso
senza pr oblemi.
Allo stesso modo, un ar r ay è un insieme di scatole, tutte una vicina all'altr a (tanto nell'esempio quando nella posizione
fisica all'inter no della memor ia), a for mar e un'unica fila che per comodità si indica con un solo nome. Per distinguer e
ogni "scompar to" si fa uso di un numer o inter o (che per convenzione è un inter o a 32 bit, ossia Integer ), detto indice.
Tutti i linguaggi .NET utilizzano sempr e un indice a base 0: ciò significa che si inizia a contar e da 0 anziché da 1:
La sintassi usata per dichiar ar e un ar r ay è simile a quella usata per dichiar ar e una singola var iabile:
1. Dim [nome]([numero elementi - 1]) As [tipo]
La differ enza tr a le due r isiede nelle par entesi tonde che vengono poste dopo il nome della var iabile. Tr a queste
32. par entesi può anche esser e specificato un numer o (sempr e inter o, ovviamente) che indica l'indice massimo a cui si può
ar r ivar e: dato che, come abbiamo visto, gli indici sono sempr e a base 0, il numer o effettivo di elementi pr esenti nella
collezione sar à di un'unità super ior e r ispetto all'indice massimo. Ad esempio, con questo codice:
1. Dim A(5) As String
il pr ogr ammator e indica al pr ogr amma che la var iabile A è un ar r ay contenente questi elementi:
1. A(0), A(1), A(2), A(3), A(4), A(5)
che sono per la pr ecisione 6 elementi. Ecco un listato che esemplifica i concetti fin'or a chiar iti:
01. Module Module1
02. Sub Main()
03. 'Array che contiene 10 valori decimali, rappresentanti voti
04. Dim Marks(9) As Single
05. 'Questa variabile terrà traccia di quanti voti
06. 'l'utente avrà immesso da tastiera e permetterà di
07. 'calcolarne una media
08. Dim Index As Int32 = 0
09.
10. 'Mark conterrà il valore temporaneo immesso
11. 'da tastiera dall'utente
12. Dim Mark As Single
13. Console.WriteLine("Inserisci un altro voto (0 per terminare):")
14. Mark = Console.ReadLine
15.
16. 'Il ciclo finisce quando l'utente immette 0 oppure quando
17. 'si è raggiunto l'indice massimo che è
18. 'possibile usare per identificare una cella dell'array
19. Do While (Mark > 0) And (Index < 10)
20. 'Se il voto immesso è maggiore di 0, lo memorizza
21. 'nell'array e incrementa l'indice di 1, così da
22. 'poter immagazzinare correttamente il prossimo voto nell'array
23. Marks(Index) = Mark
24. Index += 1
25.
26. Console.WriteLine("Inserisci un altro voto (0 per terminare):")
27. Mark = Console.ReadLine
28. Loop
29. 'Decrementa l'indice di 1, poiché anche se l'utente
30. 'ha immesso 0, nel ciclo precedente, l'indice era stato
31. 'incrementato prevedendo un'ulteriore immissione, che,
32. 'invece, non c'è stata
33. Index -= 1
34.
35. 'Totale dei voti
36. Dim Total As Single = 0
37. 'Usa un ciclo For per scorrere tutte le celle dell'array
38. 'e sommarne i valori
39. For I As Int32 = 0 To Index
40. Total += Marks(I)
41. Next
42.
43. 'Mostra la media
44. Console.WriteLine("La tua media è: " & (Total / (Index + 1)))
45. Console.ReadKey()
46. End Sub
47. End Module
Il codice potr ebbe non appar ir e subito chiar o a pr ima vista, ma attr aver so uno sguar do più attento, tutto si far à più
limpido. Di seguito è scr itto il flusso di elabor azione del pr ogr amma ammettendo che l'utente immetta due voti:
Richiede un voto da tastier a: l'utente immette 5 (Mar k = 5)
Mar k è maggior e di 0
Inser isce il voto nell'ar r ay: Mar ks(Index ) = Mar ks(0) = 5
Incr ementa Index di 1: Index = 1
33. Entr ambe le condizioni non sono ver ificate: Mar k <> 0 e Index < 9. Il ciclo continua
Richiede un voto da tastier a: l'utente immette 10 (Mar k = 10)
Mar k è maggior e di 0
Inser isce il voto nell'ar r ay: Mar ks(Index ) = Mar ks(1) = 10
Incr ementa Index di 1: Index = 2
Entr ambe le condizioni non sono ver ificate: Mar k <> 0 e Index < 9. Il ciclo continua
Richiede un voto da tastier a: l'utente immette 0 (Mar k = 0)
Mar k è uguale a 0: il codice dentr o if non viene eseguito
Una delle condizioni di ar r esto è ver ificata: Mar k = 0. Il ciclo ter mina
Decr ementa Index di 1: Index = 1
Somma tutti i valor i in Mar ks da 0 a Index (=1): Total = Mar ks(0) + Mar ks(1) = 5 + 10
Visualizza la media: Total / (Index + 1) = 15 / (1 + 1) = 15 / 2 = 7.5
Attende la pr essione di un tasto per uscir e
È anche possibile dichiar ar e ed inizializzar e (ossia r iempir e) un ar r ay in una sola r iga di codice. La sintassi usata è la
seguente:
1. Dim [nome]() As [tipo] = {elementi dell'array separati da virgole}
Ad esempio:
1. Dim Parole() As String = {"ciao", "mouse", "penna"}
Questa sintassi br eve equivale a questo codice:
1. Dim Parole(2) As String
2. Parole(0) = "ciao"
3. Parole(1) = "mouse"
4. Parole(2) = "penna"
Un'ulter ior e sintassi usata per dichiar ar e un ar r ay è la seguente:
1. Dim [nome] As [tipo]()
Quest'ultima, come vedr emo, sar à par ticolar mente utile nel gestir e il tipo r estituito da una funzione.
Array a più dimensioni
Gli ar r ay a una dimensione sono contr addistinti da un singolo indice: se volessimo par agonar li ad un ente geometr ico,
sar ebber o assimilabili ad una r etta, estesa in una sola dimensione, in cui ogni punto r appr esenta una cella dell'ar r ay.
Gli ar r ay a più dimensioni, invece, sono contr addistinti da più di un indice: il numer o di indici che identifica
univocamente un elemento dell'ar r ay di dice r ang o . Un ar r ay di r ango 2 (a 2 dimensioni) potr à, quindi, esser e
par agonato a un piano, o ad una gr iglia di scatole estesa in lunghezza e in lar ghezza. La sintassi usata è:
1. Dim [nome]( , ) As [tipo] 'array di rango 2
2. Dim [nome]( , , ) As [tipo] 'array di rango 3
Ecco un esempio che consider a un ar r ay di r ango 2 come una matr ice quadr ata:
01. Module Module1
02. Sub Main()
03. 'Dichiara e inizializza un array di rango 2. Dato che
04. 'in questo caso abbiamo due dimensioni, e non una sola,
05. 'non si può specificare una semplice lista di
06. 'valori, ma una specie di "tabella" a due entrate.
07. 'Nell'esempio che segue, ho creato una semplice
08. 'tabella a due righe e due colonne, in cui ogni cella
09. 'è 0.
10.
34. Dim M(,) As Single = _
11. {{0, 0}, _
12. {0, 0}}
13. 'Bisogna notare il particolare uso delle graffe: si
14. 'considera l'array di rango 2 come un array i cui
15. 'elementi sono altri array
16.
17. Console.WriteLine("Inserire gli elementi della matrice:")
18. For I As Int32 = 0 To 1
19. For J As Int32 = 0 To 1
20. Console.Write("Inserire l'elemento (" & I & ", " & J & "): ")
21. M(I, J) = Console.ReadLine
22. Next
23. Next
24.
25. Dim Det As Single
26. Det = M(0, 0) * M(1, 1) - M(0, 1) * M(1, 0)
27. Console.WriteLine("Il determinante della matrice è: " & Det)
28.
29. Console.ReadKey()
30. End Sub
31. End Module
Rappr esentando gr aficamente l'ar r ay M, potr emmo disegnar lo così:
Ma il computer lo può anche veder e in questo modo, come un ar r ay di ar r ay:
35. Come si vede dal codice di inizializzazione, seppur concettualmente diver si, i due modi di veder e un ar r ay sono
compatibili. Tuttavia, bisogna chiar ir e che so lo e so ltanto in questo caso, le due visioni sono conciliabili, poiché un
ar r ay di r ango 2 e un ar r ay di ar r ay sono, dopo tutto, due entità ben distinte. Infatti, esiste un modo per dichiar ar e
ar r ay di ar r ay, come segue:
1. Dim [nome]()() As [tipo] 'array di array
E se si pr ova a far e una cosa del gener e:
1. Dim A(,) As Int32
2. Dim B()() As Int32
3. '...
4. A = B
Si r iceve un er r or e esplicito da par te del compilator e.
Ridimensionare un array
Può capitar e di dover modificar e la lunghezza di un ar r ay r ispetto alla dichiar azione iniziale. Per far e questo, si usa la
par ola r iser vata ReDim, da non confonder e con la keyw or d Dim: hanno due funzioni totalmente differ enti. Quando si
r idimensiona un ar r ay, tutto il suo contenuto viene cancellato: per evitar e questo inconveniente, si deve usar e
l'istr uzione ReDim Pres erve, che tuttavia ha pr estazioni molto scar se a causa dell'eccessiva lentezza. Entr ambe le
istr uzioni der ivano dal Visual Basic classico e non fanno par te, per tanto, della sintassi .NET, sebbene continuino ad
esser e molto usate, sia per comodità, sia per abitudine. Il metodo più cor r etto da adottar e consiste nell'usar e la
pr ocedur a Ar r ay.Resize. Eccone un esempio:
01. Module Module1
02. Sub Main()
03. Dim A() As Int32
04. Dim n As Int32
05.
06. Console.WriteLine("Inserisci un numero")
07. n = Console.ReadLine
08.
09. 'Reimposta la lunghezza di a ad n elementi
10. Array.Resize(A, n)
11.
12. 'Calcola e memorizza i primi n numeri pari (zero compreso)
13. For I As Int16 = 0 To n - 1
14. A(I) = I * 2
15. Next
16.
17. Console.ReadKey()
18. End Sub
19. End Module
La r iga Ar r ay.Resize(A, n) equivale, usando ReDim a:
1. ReDim A(n - 1)
Per r idimensionar e un ar r ay a più dimensioni, la faccenda si fa abbastanza complessa. Per pr ima cosa, non si può
utilizzar e Ar r ay.Resize a meno che non si utilizzi un ar r ay di ar r ay, ma anche in quel caso le cose non sono semplici.
Infatti, è possibile stabilir e la lunghezza di una sola dimensione alla volta. Ad esempio, avendo un ar r ay M di r ango 2
con nove elementi, r aggr uppati in 3 r ighe e 3 colonne, non si può semplicemente scr iver e:
1. ReDim M(2, 2)
36. per chè, così facendo, solo la r iga 2 ver r à r idimensionata a 3 elementi, mentr e la 0 e la 1 sar anno vuote. Il codice da
usar e, quindi, è:
1. ReDim M(0, 2)
2. ReDim M(1, 2)
3. ReDim M(2, 2)
In questo modo, ogni "r iga" viene aggiustata alla lunghezza giusta.
37. A12. Gli Array - Parte II
Il c ostrutto iterativo For Eac h
Questo costr utto iter ativo è simile al nor male For , ma, invece di aver e una var iabile contator e numer ica, ha una
var iabile contator e di var io tipo. In sostanza, questo ciclo iter a attr aver so una ar r ay o una collezione di altr o gener e,
selezionando, di volta in volta, l'elemento che si tr ova alla posizione cor r ente nell'ar r ay. Il suo funzionamento intr inseco
è tr oppo complesso da spiegar e or a, quindi lo affr onter ò solamente nei capitoli dedicati alle inter facce, in par ticolar e
par lando dell'inter faccia IEnumer able. La sintassi è la seguente:
1. Dim A As [tipo]
2. For Each A In [array/collezione]
3. 'istruzioni
4. Next
Ovviamente anche in questo caso, come nel nor male For , è possibile inizializzar e una var iabile contator e all'inter no del
costr utto:
1. For Each A As [tipo] in [array/collezione] ...
Esempio:
01. Module Module1
02. Sub Main()
03. Dim Words() As String = {"Questo", "è", "un", "array", "di", "stringhe"}
04.
05. For Each Str As String In Words
06. Console.Write(Str & " ")
07. Next
08.
09. 'A schermo apparirà la frase:
10. ' "Questo è un array di stringhe "
11.
12. Console.ReadKey()
13. End Sub
14. End Module
Per aver e un ter mine di par agone, il semplicissimo codice pr oposto equivale, usando un for nor male, a questo:
1. 'Words.Length restituisce il numero di elementi
2. 'presenti nell'array Words
3. For I As Int32 = 0 To Words.Length - 1
4. Console.Write(Words(I) & " ")
5. Next
Gli array sono un tipo referenc e
Diver samente da come accade in altr i linguaggi, gli ar r ay sono un tipo r efer ence, indipendentemente dal tipo di dati
da essi contenuto. Ciò significa che si compor tano come ho spiegato nel capitolo "Tipi r efer ence e tipi value": l'ar ea di
memor ia ad essi associata non contiene il lor o valor e, ma un puntator e alla lor o posizione nell'heap managed. Questo
significa che l'oper ator e = tr a due ar r ay non copia il contenuto di uno nell'altr o, ma li r ende identici, ossia lo stesso
oggetto. Per lo stesso motivo, è anche lecito distr ugger e logicamente un ar r ay ponendolo uguale a Nothing: questa
oper azione può salvar e un discr eto ammontar e di memor ia, ad esempio quando si usano gr andi ar r ay per la lettur a di
file binar i, ed è sempr e bene annullar e un ar r ay dopo aver lo usato.
01. Module Module1
02. Sub Main()
03.
38. 'A e B sono due array di interi
04. Dim A() As Int32 = {1, 2, 3}
05. Dim B() As Int32 = {4, 5, 6}
06.
07. 'Ora A e B sono due oggetti diversi e contengono
08. 'numeri diversi. Questa riga stamperà sullo
09. 'schermo "False", infatti A Is B = False
10. Console.WriteLine(A Is B)
11. 'Adesso poniamo A uguale a B. Dato che gli array
12. 'sono un tipo reference, da ora in poi, entrambi
13. 'saranno lo stesso oggetto
14. A = B
15. 'Infatti questa istruzione stamperà a schermo
16. ''"True", poiché A Is B = True
17. Console.WriteLine(A Is B)
18. 'Dato che A e B sono lo stesso oggetto, se modifichiamo
19. 'un valore dell'array riferendoci ad esso con il nome
20. 'B, anche richiamandolo con A, esso mostrerà
21. 'che l'ultimo elemento è lo stesso
22. B(2) = 90
23. 'Su schermo apparirà 90
24. Console.WriteLine(A(2))
25.
26. Dim C() As Int32 = {7, 8, 9}
27. B = C
28. 'Ora cosa succede?
29.
30. Console.ReadKey()
31. End Sub
32. End Module
Ecco come appar e la memor ia dopo l'assegnazione A = B:
Ed ecco come appar e dopo l'assegnazione B = C:
39. Come si vede, le var iabili contengono solo l'indir izzo degli oggetti effettivi, per ciò ogni singola var iabile (A, B o C) può
puntar e allo stesso oggetto ma anche a oggetti diver si: se A = B e B = C, non è ver o che A = C, come si vede dal gr afico.
L'indir izzo di memor ia contenuto in A non cambia se non si usa esplicitamente un oper ator e di assegnamento.
Se state leggendo la guida un capitolo alla volta, potete fer mar vi qui: il pr ossimo par agr afo è utile solo per
consultazione.
Manipolazione di array
La classe System.Ar r ay contiene molti metodi statici utili per la manipolazione degli ar r ay. I più usati sono:
Clear (A, I, L) : cancella L elementi a par tir e dalla posizione I nell'ar r ay A
Clone() : cr ea una coppia esatta dell'ar r ay
Constr ainedCopy(A1, I1, A2, I2, L) : copia L elementi dall'ar r ay A1 a par tir e dall'indice I1 nell'ar r ay A2, a par tir e
dall'indice I2; se la copia non ha successo, ogni cambiamento sar à annullato e l'ar r ay di destinazione non subir à
alcun danno
Copy(A1, A2, L) / CopyTo(A1, A2) : il pr imo metodo copia L elementi da A1 a A2 a par tir e dal pr imo, mentr e il
secondo fa una copia totale dell'ar r ay A1 e la deposita in A2
Find / FindLast (A, P(Of T)) As T : cer ca il pr imo elemento dell'ar r ay A per il quale la funzione gener ic Of T
assegnata al delegate P r estituisce un valor e Tr ue, e ne r itor na il valor e
Find(A, P(Of T)) As T() : cer ca tutti gli elementi dell'ar r ay A per i quali la funzione gener ic Of T assegnata al
delegate P r estituisce un valor e Tr ue
FindIndex / FindLastIndex (A, P(Of T)) As Int32 : cer ca il pr imo o l'ultimo elemento dell'ar r ay A per il quale la
funzione gener ic Of T assegnata al delegate P r estituisce un valor e Tr ue, e ne r itor na l'indice
For Each(A(Of T)) : esegue un'azione A deter minata da un delegate Sub per ogni elemento dell'ar r ay
GetLength(A) : r estituisce la dimensione dell'ar r ay
Index Of(A, T) / LastIndex Of(A, T) : r estituisce il pr imo o l'ultimo indice dell'oggetto T nell'ar r ay A
Rever se(A) : inver te l'or dine di tutti gli elementi nell'ar r ay A
Sor t(A) : or dina alfabeticamente l'ar r ay A. Esistono 16 ver sioni di questa pr ocedur a, tr a le quali una accetta
40. come secondo par ametr o un oggetto che implementa un'inter faccia ICompar er che per mette di decider e come
or dinar e l'ar r ay
Molti di questi metodi, come si è visto, compr endono ar gomenti molto avanzati: quando sar ete in gr ado di
compr ender e i Gener ics e i Delegate, r itor nate a far e un salto in questo capitolo: scopr ir ete la potenza di questi
metodi.
41. A13. I Metodi - Parte I
Anatomia di un metodo
Il Fr amew or k .NET mette a disposizione dello sviluppator e un enor me numer o di classi contenenti metodi davver o utili,
già scr itti e pr onti all'uso, ma solo in pochi casi questi bastano a cr ear e un'applicazione ben str uttur ata ed elegante.
Per questo motivo, è possibile cr ear e nuovi metodi - pr ocedur e o funzioni che siano - ed usar li comodamente nel
pr ogr amma. Per lo più, si cr ea un metodo per separ ar e logicamente una cer ta par te di codice dal r esto del sor gente:
questo ser ve in pr imis a r ender e il listato più leggibile, più consultabile e meno pr olisso, ed inoltr e ha la funzione di
r acchiuder e sotto un unico nome (il nome del metodo) una ser ie più o meno gr ande di istr uzioni.
Un metodo è costituito essenzialmente da tr e par ti:
Nome : un identificator e che si può usar e in altr e par ti del pr ogr amma per in vocare il metodo, ossia per
eseguir e le istr uzioni di cui esso consta;
Elenco dei par ametr i : un elenco di var iabili attr aver so i quali il metodo può scambiar e dati con il pr ogr amma;
Cor po : contiene il codice effettivo associato al metodo, quindi tutte le istr uzioni e le oper azioni che esso deve
eseguir e
Ma or a scendiamo un po' più nello specifico...
Proc edure senza parametri
Il caso più semplice di metodo consiste in una pr ocedur a senza par ametr i: essa costituisce, gr osso modo, un
sottopr ogr amma a sè stante, che può esser e r ichiamato semplicemente scr ivendone il nome. La sua sintassi è molto
semplice:
1. Sub [nome]()
2. 'istruzioni
3. End Sub
Cr edo che vi sia subito balzato agli occhi che questo è esattamente lo stesso modo in cui viene dichiar ata la Sub Main:
per tanto, or a posso dir lo, Main è un metodo e, nella maggior par te dei casi, una pr ocedur a senza par ametr i (ma si
tr atta solo di un caso par ticolar e, come vedr emo fr a poco). Quando il pr ogr amma inizia, Main è il pr imo metodo
eseguito: al suo inter no, ossia nel suo cor po, r isiede il codice del pr ogr amma. Inoltr e, poiché facenti par ti del nover o
delle entità pr esenti in una classe, i metodi sono membr i di classe: devono, per ciò, esser e dichiar ati a livello di clas s e.
Con questa locuzione abbastanza comune nell'ambito della pr ogr ammazione si intende l'atto di dichiar ar e qualcosa
all'inter no del cor po di una classe, ma fuor i dal cor po di un qualsiasi suo membr o. Ad esempio, la dichiar azione seguente
è cor r etta:
01. Module Module1
02. Sub Esempio()
03. 'istruzioni
04. End Sub
05.
06. Sub Main()
07. 'istruzioni
08. End Sub
09. End Module
mentr e la pr ossima è SBAGLI ATA:
1. Module Module1
2. Sub Main()
3.
42. Sub Esempio()
4. 'istruzioni
5. End Sub
6. 'istruzioni
7. End Sub
8. End Module
Allo stesso modo, i metodi sono l'unica categor ia, oltr e alle pr opr ietà e agli oper ator i, a poter contener e delle
istr uzioni: sono str umenti "attivi" di pr ogr ammazione e solo lor o possono eseguir e istr uzioni. Quindi astenetevi dallo
scr iver e un abominio del gener e:
1. Module Module1
2. Sub Main()
3. 'istruzioni
4. End Sub
5. Console.WriteLine()
6. End Sub
E' totalmente e concettualmente sbagliato. Ma or a veniamo al dunque con un esempio:
01. Module Module1
02. 'Dichiarazione di una procedura: il suo nome è "FindDay", il
03. 'suo elenco di parametri è vuoto, e il suo corpo è
04. 'rappresentato da tutto il codice compreso tra "Sub FindDay()"
05. 'ed "End Sub".
06. Sub FindDay()
07. Dim StrDate As String
08. Console.Write("Inserisci giorno (dd/mm/yyyy): ")
09. StrDate = Console.ReadLine
10.
11. Dim D As Date
12. 'La funzione Date.TryParse tenta di convertire la stringa
13. 'StrDate in una variabile di tipo Date (che è un tipo
14. 'base). Se ci riesce, ossia non ci sono errori nella
15. 'data digitata, restituisce True e deposita il valore
16. 'ottenuto in D; se, al contrario, non ci riesce,
17. 'restituisce False e D resta vuota.
18. 'Quando una data non viene inizializzata, dato che è un
19. 'tipo value, contiene un valore predefinito, il primo
20. 'Gennaio dell'anno 1 d.C. a mezzogiorno in punto.
21. If Date.TryParse(StrDate, D) Then
22. 'D.DayOfWeek contiene il giorno della settimana di D
23. '(lunedì, martedì, eccetera...), ma in un
24. 'formato speciale, l'Enumeratore, che vedremo nei
25. 'prossimi capitoli.
26. 'Il ".ToString()" converte questo valore in una
27. 'stringa, ossia in un testo leggibile: i giorni della
28. 'settimana, però, sono in inglese
29. Console.WriteLine(D.DayOfWeek.ToString())
30. Else
31. Console.WriteLine(StrDate & " non è una data valida!")
32. End If
33. End Sub
34.
35. 'Altra procedura, simile alla prima
36. Sub CalculateDaysDifference()
37. Dim StrDate1, StrDate2 As String
38. Console.Write("Inserisci il primo giorno (dd/mm/yyyy): ")
39. StrDate1 = Console.ReadLine
40. Console.Write("Inserisci il secondo giorno (dd/mm/yyyy): ")
41. StrDate2 = Console.ReadLine
42.
43. Dim Date1, Date2 As Date
44.
45. If Date.TryParse(StrDate1, Date1) And _
46. Date.TryParse(StrDate2, Date2) Then
47. 'La differenza tra due date restituisce il tempo
48. 'trascorso tra l'una e l'altra. In questo caso noi
49. 'prendiamo solo i giorni
50. Console.WriteLine((Date2 - Date1).Days)
51.