Skip to content

2. Nozioni di base sul linguaggio VB.NET

2.1. Introduzione

Tratteremo innanzitutto VB.NET come un linguaggio di programmazione tradizionale. Tratteremo gli oggetti in seguito.

In un programma ci sono due elementi

  • i dati
  • le istruzioni che li manipolano

In genere ci sforziamo di separare i dati dalle istruzioni:

2.2. Dati VB.NET

VB.NET utilizza i seguenti tipi di dati:

  1. interi, reali e decimali
  1. caratteri e stringhe
  2. Booleani
  3. date
  4. oggetti

2.2.1. Tipi di dati predefiniti

Tipo VB
Tipo .NET equivalente
Dimensione
Intervallo di valori
Booleano
System.Boolean
2 byte
Vero o Falso.
Byte
System.Byte
1 byte
Da 0 a 255 (senza segno).
Char
System.Char
2 byte
Da 0 a 65.535 (senza segno).
Data
System.DateTime
8 byte
Da 00:00:00 del 1° gennaio 0001 a 23:59:59 del 31 dicembre 9999.
Decimale
System.Decimal
16 byte
Da 0 a +/-79.228.162.514.264.337.593.543.950.335 senza decimali; da 0 a +/-7,9228162514264337593543950335 con 28 decimali; il numero non nullo più piccolo è +/-0,0000000000000000000000000001 (+/-1E-28).
Double
System.Double
8 byte
da -1,79769313486231E+308 a
-4,94065645841247E-324 per i valori negativi; da 4,94065645841247E-324 a 1,79769313486231E+308 per i valori positivi.
Integer
System.Int32
4 byte
Da -2.147.483.648 a 2.147.483.647.
Lungo
System.Int64
8 byte
Da -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807.
Oggetto
System.Object
4 byte
Qualsiasi tipo può essere memorizzato in una variabile di tipo Object.
Short
System.Int16
2 byte
Da -32.768 a 32.767.
Single
System.Single
4 byte
Da -3,402823E+38 a -1,401298E-45 per i valori negativi; da 1,401298E-45 a 3,402823E+38 per i valori positivi.
String
System.String (classe)
 
Da 0 a circa 2 miliardi di caratteri Unicode.

Nella tabella sopra riportata, vediamo che esistono due possibili tipi per un intero a 32 bit: Integer e System.Int32. I due tipi sono intercambiabili. Lo stesso vale per altri tipi VB e i loro equivalenti nella piattaforma .NET. Ecco un programma di esempio:


Module types
    Sub Main()
        ' whole numbers
        Dim var1 As Integer = 100
        Dim var2 As Long = 10000000000L
        Dim var3 As Byte = 100
        Dim var4 As Short = 4
        ' real numbers
        Dim var5 As Decimal = 4.56789D
        Dim var6 As Double = 3.4
        Dim var7 As Single = -0.000103F
        ' date
        Dim var8 As Date = New Date(2003, 1, 1, 12, 8, 4)
        ' boolean
        Dim var9 As Boolean = True
        ' character
        Dim var10 As Char = "A"c
        ' character string
        Dim var11 As String = "abcde"
        ' object
        Dim var12 As Object = New Object
        ' displays
        Console.Out.WriteLine("var1=" + var1.ToString)
        Console.Out.WriteLine("var2=" + var2.ToString)
        Console.Out.WriteLine("var3=" + var3.ToString)
        Console.Out.WriteLine("var4=" + var4.ToString)
        Console.Out.WriteLine("var5=" + var5.ToString)
        Console.Out.WriteLine("var6=" + var6.ToString)
        Console.Out.WriteLine("var7=" + var7.ToString)
        Console.Out.WriteLine("var8=" + var8.ToString)
        Console.Out.WriteLine("var9=" + var9.ToString)
        Console.Out.WriteLine("var10=" + var10)
        Console.Out.WriteLine("var11=" + var11)
        Console.Out.WriteLine("var12=" + var12.ToString)
    End Sub
End Module

L'esecuzione produce i seguenti risultati:

var1=100
var2=10000000000
var3=100
var4=4
var5=4,56789
var6=3,4
var7=-0,000103
var8=01/01/2003 12:08:04
var9=True
var10=A
var11=abcde
var12=System.Object

2.2.2. Notazione dei dati letterali

Intero
145, -7, &FF (esadecimale)
Lungo
100000L
Doppio
134,789, -45E-18 (-45 × 10⁻¹⁸)
Singolo
134,789F, -45E-18F (-45 × 10⁻¹⁸)
Decimale
100000D
Carattere
"A"c
String
"oggi"
Booleano
vero, falso
data
New Date(2003, 1, 1) per il 01/01/2003

Si notino i seguenti punti:

  • 100000L, dove L indica che il numero è trattato come un intero lungo
  • 134.789F, dove F indica che il numero è trattato come un numero in virgola mobile a precisione singola
  • 100000D, dove D indica che il numero viene trattato come un numero reale decimale
  • "A"c, per convertire la stringa di caratteri "A" nel carattere 'A'
  • La stringa è racchiusa tra i caratteri ". Se la stringa deve contenere il carattere ", questo va duplicato, come in "abcd""e" per rappresentare la stringa [abcd"e].

2.2.3. Dichiarazione dei dati

2.2.3.1. Ruolo delle dichiarazioni

Un programma manipola dati caratterizzati da un nome e da un tipo. Questi dati sono memorizzati in memoria. Quando il programma viene compilato, il compilatore assegna a ciascun dato una posizione di memoria caratterizzata da un indirizzo e da una dimensione. Lo fa utilizzando le dichiarazioni effettuate dal programmatore. Inoltre, queste dichiarazioni consentono al compilatore di rilevare errori di programmazione. Pertanto, l'operazione x = x \* 2 verrà dichiarata un errore se x è una stringa, ad esempio.

2.2.3.2. Dichiarazione delle costanti

La sintassi per dichiarare una costante è la seguente:

const identificatore as tipo=valore

Ad esempio, [const PI as double=3.141592]. Perché dichiarare le costanti?

  1. Il programma sarà più facile da leggere se alla costante viene assegnato un nome significativo: [const VAT_rate as single=0.186F]
  2. Modificare il programma sarà più facile se la "costante" deve essere cambiata. Quindi, nel caso precedente, se l'aliquota IVA cambia al 33%, l'unica modifica necessaria sarà cambiare l'istruzione che definisce il suo valore: [const vatrate as single=0.336F]. Se 0.186 fosse stato usato esplicitamente nel programma, numerose istruzioni dovrebbero essere modificate.

2.2.3.3. Dichiarazione delle variabili

Una variabile è identificata da un nome e fa riferimento a un tipo di dati. VB.NET non distingue tra lettere maiuscole e minuscole. Pertanto, le variabili FIN e fin sono identiche. Le variabili possono essere inizializzate al momento della loro dichiarazione. La sintassi per dichiarare una o più variabili è:

dim variabile1,variabile2,...,variabile n come identificatore_tipo

dove identificatore_tipo è un tipo predefinito o un tipo definito dal programmatore.

2.2.4. Conversioni tra numeri e stringhe

numero -> stringa
number.ToString oppure "" & number oppure CType(number, String)
oggetto -> stringa
oggetto.ToString
stringa -> Integer
Integer.Parse(stringa) o Int32.Parse
stringa -> Long
Long.Parse(stringa) o Int64.Parse
stringa -> Double
Double.Parse(string)
stringa -> Single
Single.Parse(string)

La conversione di una stringa in un numero potrebbe non andare a buon fine se la stringa non rappresenta un numero valido. Ciò provoca un errore irreversibile, noto come eccezione in VB.NET. Questo errore può essere gestito utilizzando il seguente blocco try/catch:

try
        appel de la fonction susceptible de générer l'exception
 catch e as Exception
        traiter l'exception e
end try
instruction suivante

Se la funzione non genera un'eccezione, si procede all'istruzione successiva; altrimenti, si entra nel corpo della clausola catch e poi si procede all'istruzione successiva. Torneremo più avanti alla gestione delle eccezioni. Ecco un programma che illustra le principali tecniche di conversione tra numeri e stringhe. In questo esempio, la funzione display stampa il valore del suo parametro sullo schermo. Quindi, display(S) stampa il valore di S sullo schermo.


' guidelines
Option Strict On
 
' imported namespaces
Imports System
 
' the test module
Module Module1
 
    Sub Main()
        ' main proceedings
        ' local data
        Dim S As String
        Const i As Integer = 10
        Const l As Long = 100000
        Const f As Single = 45.78F
        Dim d As Double = -14.98
 
        ' number --> string
        affiche(CType(i, String))
        affiche(CType(l, String))
        affiche(CType(f, String))
        affiche(CType(d, String))
 
        'boolean --> string
        Const b As Boolean = False
        affiche(b.ToString)
 
        ' string --> int
        Dim i1 As Integer = Integer.Parse("10")
        affiche(i1.ToString)
        Try
            i1 = Integer.Parse("10.67")
            affiche(i1.ToString)
        Catch e As Exception
            affiche("Erreur [10.67] : " + e.Message)
        End Try
 
        ' chain --> long
        Dim l1 As Long = Long.Parse("100")
        affiche("" + l1.ToString)
        Try
            l1 = Long.Parse("10.675")
            affiche("" & l1)
        Catch e As Exception
            affiche("Erreur [10.675] : " + e.Message)
        End Try
 
        ' chain --> double
        Dim d1 As Double = Double.Parse("100,87")
        affiche(d1.ToString)
        Try
            d1 = Double.Parse("abcd")
            affiche("" & d1)
        Catch e As Exception
            affiche("Erreur [abcd] : " + e.Message)
        End Try
 
        ' chain --> single
        Dim f1 As Single = Single.Parse("100,87")
        affiche(f1.ToString)
        Try
            d1 = Single.Parse("abcd")
            affiche(f1.ToString)
        Catch e As Exception
            affiche("Erreur [abcd] : " + e.Message)
        End Try
    End Sub
 
    ' poster
    Public Sub affiche(ByVal S As String)
        Console.Out.WriteLine("S=" + S)
    End Sub
End Module

I risultati sono i seguenti:

S=10
S=100000
S=45,78
S=-14,98
S=False
S=10
S=Erreur [10.67] : Le format de la chaîne d'entrée est incorrect.
S=100
S=Erreur [10.675] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.

Si noti che i numeri reali in forma di stringa devono utilizzare una virgola, non un punto decimale. Pertanto, scriviamo Dim d As Double = -14.98 ma Dim d1 As Double = Double.Parse("100.87")

2.2.5. Array di dati

Un array VB.NET è un oggetto che consente di raggruppare dati dello stesso tipo sotto un unico identificatore. Viene dichiarato come segue:

Dim Array(n) As Type oppure Dim Array() As Type = New Type(n) {}

dove n è l'indice dell'ultimo elemento dell'array. La sintassi Array(i) si riferisce ai dati all'indice i, dove i appartiene all'intervallo [0,n]. Qualsiasi riferimento ai dati Array(i) in cui i non appartiene all'intervallo [0,n] causerà un'eccezione. Un array può essere inizializzato contemporaneamente alla sua dichiarazione. In questo caso, non è necessario specificare l'indice dell'ultimo elemento.


        Dim entiers() As Integer = {0, 10, 20, 30}

Gli array hanno una proprietà Length, che indica il numero di elementi presenti nell'array. Ecco un programma di esempio:


Module tab0
    Sub Main()
        ' a first picture
        Dim tab0(5) As Integer
        For i As Integer = 0 To UBound(tab0)
            tab0(i) = i
        Next
        For i As Integer = 0 To UBound(tab0)
            Console.Out.WriteLine("tab0(" + i.ToString + ")=" + tab0(i).tostring)
        Next
 
        ' a second panel
        Dim tab1() As Integer = New Integer(5) {}
        For i As Integer = 0 To tab1.Length - 1
            tab1(i) = i * 10
        Next
        For i As Integer = 0 To tab1.Length - 1
            Console.Out.WriteLine("tab1(" + i.ToString + ")=" + tab1(i).tostring)
        Next
    End Sub
End Module

e la sua esecuzione:

tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50

Un array bidimensionale può essere dichiarato come segue:

Dim Array(n, m) as Tipo oppure Dim Array(,) as Tipo = New Tipo(n, m) {}

dove n+1 è il numero di righe, m+1 il numero di colonne. La sintassi Array(i,j) si riferisce all'elemento j nella riga i di Array. L'array bidimensionale può anche essere inizializzato nel momento stesso in cui viene dichiarato:


        Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}

Il numero di elementi in ciascuna dimensione può essere ottenuto utilizzando il metodo GetLength(i), dove i=0 rappresenta la dimensione corrispondente al primo indice, i=1 la dimensione corrispondente al secondo indice, … Ecco un programma di esempio:


Module Module2
    Sub Main()
        ' a first picture
        Dim tab0(2, 1) As Integer
        For i As Integer = 0 To UBound(tab0)
            For j As Integer = 0 To tab0.GetLength(1) - 1
                tab0(i, j) = i * 10 + j
            Next
        Next
        For i As Integer = 0 To UBound(tab0)
            For j As Integer = 0 To tab0.GetLength(1) - 1
                Console.Out.WriteLine("tab0(" + i.ToString + "," + j.ToString + ")=" + tab0(i, j).tostring)
            Next
        Next
 
        ' a second panel
        Dim tab1(,) As Integer = New Integer(2, 1) {}
        For i As Integer = 0 To tab1.GetLength(0) - 1
            For j As Integer = 0 To tab1.GetLength(1) - 1
                tab1(i, j) = i * 100 + j
            Next
        Next
        For i As Integer = 0 To tab1.GetLength(0) - 1
            For j As Integer = 0 To tab1.GetLength(1) - 1
                Console.Out.WriteLine("tab1(" + i.ToString + "," + j.ToString + ")=" + tab1(i, j).tostring)
            Next
        Next
    End Sub
End Module

e i risultati della sua esecuzione:

tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50

Un array di array viene dichiarato come segue:

Dim Array(n)() As Tipo oppure Dim Array()() As Tipo = New Tipo(n)()

La dichiarazione sopra riportata crea un array di n+1 righe. Ogni elemento Array(i) è un riferimento a un array unidimensionale. Questi array non vengono creati durante la dichiarazione sopra riportata. L'esempio seguente illustra la creazione di un array di array:


        ' a table of tables
        Dim noms()() As String = New String(3)() {}
        ' initialization
        For i = 0 To noms.Length - 1
            noms(i) = New String(i) {}
            For j = 0 To noms(i).Length - 1
                noms(i)(j) = "nom" & i & j
            Next
        Next

Qui, names(i) è un array di i+1 elementi. Poiché names(i) è un array, names(i).Length è il numero di elementi che contiene. Ecco un esempio che combina i tre tipi di array appena discussi:


' guidelines
Option Strict On
Option Explicit On 
 
' imports
Imports System
 
' test class
Module test
    Sub main()
        ' an initialized 1-dimensional array
        Dim entiers() As Integer = {0, 10, 20, 30}
        Dim i As Integer
        For i = 0 To entiers.Length - 1
            Console.Out.WriteLine("entiers[" & i & "]=" & entiers(i))
        Next
 
        ' an initialized 2-dimensional array
        Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}
        Dim j As Integer
        For i = 0 To réels.GetLength(0) - 1
            For j = 0 To réels.GetLength(1) - 1
                Console.Out.WriteLine("réels[" & i & "," & j & "]=" & réels(i, j))
            Next
        Next
 
        ' an array°of arrays
        Dim noms()() As String = New String(3)() {}
 
        ' initialization
        For i = 0 To noms.Length°- 1
            noms(i) =°New String(i) {}
            For j = 0 To noms(i).Length - 1
                noms(i)(j) = "nom" & i & j
            Next
        Next
 
        ' display
        For i = 0 To noms.Length°- 1
            For j = 0 To noms(i).Length - 1
                Console.Out.WriteLine("noms[" & i & "][" & j & "]=" & noms(i)(j))
            Next
        Next
    End Sub
End Module

Una volta eseguito, otteniamo i seguenti risultati:

entiers[0]=0
entiers[1]=10
entiers[2]=20
entiers[3]=30
réels[0,0]=0,5
réels[0,1]=1,7
réels[1,0]=8,4
réels[1,1]=-6
noms[0][0]=nom00
noms[1][0]=nom10
noms[1][1]=nom11
noms[2][0]=nom20
noms[2][1]=nom21
noms[2][2]=nom22
noms[3][0]=nom30
noms[3][1]=nom31
noms[3][2]=nom32
noms[3][3]=nom33

2.3. Istruzioni di base di VB.NET

Distinguiamo tra

1 le istruzioni di base eseguite dal computer.

2 le istruzioni che controllano il flusso del programma.

Le istruzioni di base diventano chiare se si considera la struttura di un microcomputer e delle sue periferiche.

  1. Lettura delle informazioni dalla tastiera

  2. Elaborazione delle informazioni

  3. Scrittura delle informazioni sullo schermo

  4. Lettura delle informazioni da un file su disco

  5. Scrittura di informazioni su un file su disco

2.3.1. Scrittura sullo schermo

Esistono varie istruzioni per la scrittura sullo schermo:

Console.Out.WriteLine(expression)
Console.WriteLine(expression)
Console.Error.WriteLine (expression)

dove espressione è un tipo di dati qualsiasi che può essere convertito in una stringa da visualizzare sullo schermo. Negli esempi visti finora, abbiamo utilizzato solo l'istruzione Console.Out.WriteLine(espressione).

La classe System.Console consente di eseguire operazioni di scrittura sullo schermo (Write, WriteLine). La classe Console dispone di due proprietà, Out ed Error, che sono flussi di scrittura di tipo StreamWriter:

  • Console.WriteLine() è equivalente a Console.Out.WriteLine() e scrive nello stream Out, che di solito è associato allo schermo.
  • Console.Error.WriteLine() scrive nel flusso Error, che di solito è anch'esso associato allo schermo.

I flussi Out ed Error sono associati allo schermo per impostazione predefinita. Tuttavia, possono essere reindirizzati a file di testo in fase di esecuzione, come vedremo tra poco.

2.3.2. Lettura dei dati digitati sulla tastiera

Il flusso di dati proveniente dalla tastiera è rappresentato dall'oggetto Console.In di tipo StreamReader. Questo tipo di oggetto consente di leggere una riga di testo utilizzando il metodo ReadLine:


        Dim ligne As String = Console.In.ReadLine()

La riga digitata sulla tastiera viene memorizzata nella variabile line* e può quindi essere utilizzata dal programma. Il flusso In può essere reindirizzato a un file, proprio come i flussi Out e Error*.

2.3.3. Esempio di input/output

Ecco un breve programma che illustra le operazioni di input/output da tastiera/schermo:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
' module
Module io1
    Sub Main()
        ' write to Out feed
        Dim obj As New Object
        Console.Out.WriteLine(("" & obj.ToString))
 
        ' write to the Error stream
        Dim i As Integer = 10
        Console.Error.WriteLine(("i=" & i))
 
        ' reading a line entered on the keyboard
        Console.Out.Write("Tapez une ligne : ")
        Dim ligne As String = Console.In.ReadLine()
        Console.Out.WriteLine(("ligne=" + ligne))
    End Sub
End Module

e i risultati dell'esecuzione:

System.Object
i=10
Tapez une ligne : ceci est un essai
ligne=ceci est un essai

Le istruzioni


        Dim obj As New Object
        Console.Out.WriteLine(obj.ToString)

sono presenti solo per dimostrare che qualsiasi oggetto può essere visualizzato. In questa sede non tenteremo di spiegare il significato di ciò che viene visualizzato.

2.3.4. Reindirizzamento I/O

In DOS/Windows, ci sono tre dispositivi di input standard chiamati:

  1. dispositivo di input standard — per impostazione predefinita si riferisce alla tastiera ed è numerato 0
  2. dispositivo di output standard — di default è lo schermo ed è numerato 1
  3. dispositivo di errore standard: di default si riferisce allo schermo ed è numerato 2

In VB.NET, il flusso di output Console.Out scrive sul dispositivo 1, il flusso di output Console.Error scrive sul dispositivo 2 e il flusso di input Console.In legge i dati dal dispositivo 0. Quando si esegue un programma in una finestra DOS in Windows, è possibile specificare quali dispositivi saranno 0, 1 e 2 per il programma in esecuzione. Si consideri la seguente riga di comando:

pg arg1 arg2 .. argn

Dopo gli argomenti argi del programma pg, è possibile reindirizzare i dispositivi di I/O standard verso dei file:

0<in.txt
Il flusso di input standard n. 0 viene reindirizzato al file in.txt. Nel programma, il flusso Console.In leggerà quindi i propri dati dal file in.txt.
  
1>out.txt
reindirizza il flusso di output n. 1 al file out.txt. Ciò significa che nel programma, il flusso Console.Out scriverà i propri dati nel file out.txt
   
1>>out.txt
Come sopra, ma i dati scritti vengono aggiunti al contenuto corrente del file out.txt.
   
2>error.txt
reindirizza l'output n. 2 al file error.txt. Ciò significa che nel programma, il flusso Console.Error scriverà i propri dati nel file error.txt
   
2>>error.txt
Come sopra, ma i dati scritti vengono aggiunti al contenuto corrente del file error.txt.
   
1>out.txt 2>error.txt
I dispositivi 1 e 2 vengono entrambi reindirizzati ai file
   

Si noti che per reindirizzare i flussi di I/O del programma pg verso dei file, non è necessario modificare il programma pg. È il sistema operativo a determinare la natura dei dispositivi 0, 1 e 2. Si consideri il seguente programma:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
' redirections
Module console2
    Sub Main()
        ' lecture flux In
        Dim data As String = Console.In.ReadLine()
        ' write Out feed
        Console.Out.WriteLine(("écriture dans flux Out : " + data))
        ' écriture flux Error
        Console.Error.WriteLine(("écriture dans flux Error : " + data))
    End Sub
End Module

Compiliamo questo programma:

dos>vbc es2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.

dos>dir
24/02/2004  15:39                  416 es2.vb
11/03/2004  08:20                3 584 es2.exe

Eseguiamolo per la prima volta:

dos>es2.exe
un premier test
écriture dans flux Out : un premier test
écriture dans flux Error : un premier test

L'esecuzione precedente non reindirizza nessuno dei flussi di I/O standard In, Out o Error. Ora reindirizzeremo tutti e tre i flussi. Il flusso In verrà reindirizzato a un file denominato in.txt, il flusso Out a un file denominato out.txt e il flusso Error a un file denominato error.txt. Questo reindirizzamento viene eseguito sulla riga di comando come segue

dos>es2.exe 0<in.txt 1>out.txt 2>error.txt

L'esecuzione produce i seguenti risultati:

dos>more in.txt
un second test

dos>es2.exe 0<in.txt 1>out.txt 2>error.txt

dos>more out.txt
écriture dans flux Out : un second test

dos>more error.txt
écriture dans flux Error : un second test

È chiaro che i flussi Out ed Error non scrivono sugli stessi dispositivi.

2.3.5. Assegnazione del valore di un'espressione a una variabile

Qui ci interessa l'operazione variable=expression. L'espressione può essere di uno dei seguenti tipi: aritmetica, relazionale, booleana o stringa.

2.3.5.1. Elenco degli operatori

Azione
Elemento del linguaggio
Aritmetica
^, –, *, /, \, Mod, +, =
Assegnazione
=, ^=, *=, /=, \=, +=, -=, &=
Confronto
=, <>, <, >, <=, >=, Like, Is
Concatenazione
&, +
Operazioni logiche/bit a bit
Not, And, Or, Xor, AndAlso, OrElse
Operazioni varie
AddressOf, GetType

2.3.5.2. Espressione aritmetica

Gli operatori per le espressioni aritmetiche sono i seguenti:

Aritmetica
^, –, *, /, \, Mod, +, =

+: addizione, -: sottrazione, *: moltiplicazione, /: divisione in virgola mobile, \: quoziente della divisione intera, Mod: resto della divisione intera, ^: elevamento a potenza. Pertanto, il seguente programma:


' arithmetic operators
Module operateursarithmetiques
    Sub Main()
        Dim i, j As Integer
        i = 4 : j = 3
        Console.Out.WriteLine(i & "/" & j & "=" & (i / j))
        Console.Out.WriteLine(i & "\" & j & "=" & (i \ j))
        Console.Out.WriteLine(i & " mod " & j & "=" & (i Mod j))
 
        Dim r1, r2 As Double
        r1 = 4.1 : r2 = 3.6
        Console.Out.WriteLine(r1 & "/" & r2 & "=" & (r1 / r2))
        Console.Out.WriteLine(r1 & "^2=" & (r1 ^ 2))
        Console.Out.WriteLine(Math.Cos(3))
    End Sub
End Module

fornisce i seguenti risultati:

4/3=1,33333333333333
4\3=1
4 mod 3=1
4,1/3,6=1,13888888888889
4,1^2=16,81
-0,989992496600445

Esistono varie funzioni matematiche. Eccone alcune:


Funzione pubblica condivisa Sqrt(ByVal d As Double) As Double
radice quadrata

[Visual Basic]
Funzione pubblica condivisa Cos(ByVal d As Double) As Double
Coseno

Funzione pubblica condivisa Sin(ByVal a As Double) As Double
Sen

[Visual Basic]
Funzione pubblica condivisa Tan(ByVal a As Double) As Double
Tangente

[Visual Basic]
Funzione pubblica condivisa Pow(ByVal x As Double, ByVal y As Double) As Double
x elevato a y (x > 0)

[Visual Basic]
Funzione pubblica condivisa Exp(ByVal d As Double) As Double
Esponenziale

[Visual Basic]
Sovraccarichi Funzione pubblica condivisa Log( ByVal d As Double ) As Double
Logaritmo naturale

Sovraccarichi Funzione pubblica condivisa Abs(ByVal valore As Double) As Double
Valore assoluto
....
 

Tutte queste funzioni sono definite in una classe .NET chiamata Math. Quando le si utilizza, è necessario anteporre loro il nome della classe in cui sono definite. Pertanto, si scriverebbe:

        Dim r1, r2 As Double
        r2 = Math.Sqrt(9)
        r1 = Math.Cos(3)

La definizione completa della classe Math è la seguente:

E
Rappresenta il logaritmo naturale in base alla costante e.
   
PI
Rappresenta il rapporto tra la circonferenza di un cerchio e il suo diametro, indicato dalla costante π.
   
Abs
Sovraccaricato. Restituisce il valore assoluto di un numero specificato.
  
Acos
Restituisce l'angolo il cui coseno è il numero specificato.
  
Asin
Restituisce l'angolo il cui seno è il numero specificato.
  
Atan
Restituisce l'angolo la cui tangente è il numero specificato.
  
Atan2
Restituisce l'angolo la cui tangente è il quoziente di due numeri specificati.
  
BigMul
Genera il prodotto intero di due numeri a 32 bit.
  
Tetto
Restituisce il numero intero più piccolo maggiore o uguale al numero specificato.
  
Cos
Restituisce il coseno dell'angolo specificato.
  
Cosh
Restituisce il coseno iperbolico dell'angolo specificato.
  
DivRem
Sovraccaricato. Restituisce il quoziente di due numeri, passando il resto come parametro di output.
  
Exp
Restituisce e elevato alla potenza specificata.
  
Floor
Restituisce il numero intero più grande minore o uguale al numero specificato.
  
IEEERemainder
Restituisce il resto della divisione di un numero per un altro.
  
Log
Sovraccaricato. Restituisce il logaritmo di un numero specificato.
  
Log10
Restituisce il logaritmo in base 10 di un numero specificato.
  
Max
Sovraccaricato. Restituisce il più grande dei due numeri specificati.
  
Min
Sovraccaricato. Restituisce il più piccolo dei due numeri.
  
Pow
Restituisce un numero specificato elevato alla potenza specificata.
  
Arrotondamento
Sovraccaricato. Restituisce il numero più vicino al valore specificato.
  
Segno
Sovraccaricato. Restituisce un valore che indica il segno di un numero.
  
Sin
Restituisce il seno dell'angolo specificato.
  
Sinh
Restituisce il seno iperbolico dell'angolo specificato.
  
Sqrt
Restituisce la radice quadrata di un numero specificato.
  
Tan
Restituisce la tangente dell'angolo specificato.
  
Tanh
Restituisce la tangente iperbolica dell'angolo specificato.
  

Quando una funzione è dichiarata "sovraccaricata", significa che esiste per vari tipi di parametri. Ad esempio, la funzione Abs(x) esiste per x di tipo Integer, Long, Decimal, Single e Float. Per ciascuno di questi tipi, esiste una definizione separata della funzione Abs. Si dice quindi che sia sovraccaricata.

2.3.5.3. Operatori nella valutazione delle espressioni aritmetiche

La precedenza degli operatori nella valutazione di un'espressione aritmetica è la seguente (dalla più alta alla più bassa):

Categoria
Operatori
Primari
Tutte le espressioni senza operatori: funzioni, parentesi
Elevamento a potenza
^
Negazione unaria
+, -
Moltiplicazione
*, /
Divisione per un numero intero
\
Modulo
Mod
Addizione
+, -

2.3.5.4. Espressioni relazionali

Gli operatori sono i seguenti:

Confronto
=, <>, <, >, <=, >=, Like, Is

=: uguale a, <>: diverso da, <: minore di (in senso stretto), >: maggiore di (in senso stretto), <=: minore o uguale a, >=: maggiore o uguale a, Like: corrisponde a un modello, Is: identità dell'oggetto. Tutti questi operatori hanno la stessa precedenza. Vengono valutati da sinistra a destra. Il risultato di un'espressione relazionale è un valore booleano.

Confronto tra stringhe: si consideri il seguente programma:


' namespaces
Imports System
 
Module string1
    Sub main()
        Dim ch1 As Char = "A"c
        Dim ch2 As Char = "B"c
        Dim ch3 As Char = "a"c
        Console.Out.WriteLine("A<B=" & (ch1 < ch2))
        Console.Out.WriteLine("A<a=" & (ch1 < ch3))
        Dim chat As String = "chat"
        Dim chien As String = "chien"
        Dim chaton As String = "chaton"
        Dim chat2 As String = "CHAT"
        Console.Out.WriteLine("chat<chien=" & (chat < chien))
        Console.Out.WriteLine("chat<chaton=" & (chat < chaton))
        Console.Out.WriteLine("chat<CHAT=" & (chat < chat2))
        Console.Out.WriteLine("chaton like chat*=" & ("chaton" Like "chat*"))
    End Sub
End Module

e il risultato della sua esecuzione:

A<B=True
A<a=True
chat<chien=True
chat<chaton=True
chat<CHAT=False
chaton like chat*=True

Siano C1 e C2 due caratteri. Essi possono essere confrontati utilizzando gli operatori: <, <=, =, <>, >, >=. Sono i loro valori Unicode — che sono numeri — ad essere confrontati. Secondo l'ordine Unicode, valgono le seguenti relazioni:

spazio < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'

Le stringhe vengono confrontate carattere per carattere. La prima disuguaglianza riscontrata tra due caratteri implica una disuguaglianza dello stesso segno per le stringhe. Con queste spiegazioni, il lettore è invitato a esaminare i risultati del programma precedente.

2.3.5.5. Espressioni booleane

Gli operatori sono i seguenti:

Operazioni logiche/bit a bit
Not, And, Or, Xor, AndAlso, OrElse

Not: AND logico, Or: OR logico, Not: negazione, Xor: OR esclusivo.

op1 AndAlso op2: se op1 è falso, op2 non viene valutato e il risultato è falso.

op1 OrElse op2: se op1 è vero, op2 non viene valutato e il risultato è vero.

La precedenza di questi operatori l'uno rispetto all'altro è la seguente:

NOT logico
NOT logico
AND logico
E, E anche
OR logico
OR, OrElse
XOR logico
XOR

Il risultato di un'espressione booleana è un valore booleano.

2.3.5.6. Operazioni bit a bit

Da un lato, troviamo gli stessi operatori degli operatori booleani con la stessa precedenza. Troviamo anche due operatori di spostamento: << e >>. Siano i e j due numeri interi.

i<<n
sposta i di n bit a sinistra. I bit in entrata sono zeri.
i>>n
sposta i di n bit a destra. Se i è un intero con segno (signed char, int, long), il bit di segno viene mantenuto.
i & j
esegue un AND logico bit a bit tra i e j.
i | j
esegue un'operazione OR bit a bit su i e j.
~i
completa i a 1
i^j
esegue l'operazione XOR tra i e j

Si consideri il seguente programma:


Module operationsbit
    Sub main()
        ' bit manipulation
        Dim i As Short = &H123F
        Dim k As Short = &H7123
        Console.Out.WriteLine("i<<4=" & (i << 4).ToString("X"))
        Console.Out.WriteLine("i>>4=" & (i >> 4).ToString("X"))
        Console.Out.WriteLine("k>>4=" & (k >> 4).ToString("X"))
        Console.Out.WriteLine("i and 4=" & (i And 4).ToString("X"))
        Console.Out.WriteLine("i or 4 =" & (i Or 4).ToString("X"))
        Console.Out.WriteLine("not i=" & (Not i).ToString("X"))
    End Sub
End Module

La sua esecuzione produce i seguenti risultati:

i<<4=23F0
i>>4=123
k>>4=712
i and 4=4
i or k =123F
not i=EDC0

2.3.5.7. Operatore associato all'assegnazione

È possibile scrivere a+=b, che significa a=a+b. L'elenco degli operatori che possono essere combinati con l'operazione di assegnazione è il seguente:

Combinazione di operatori
^=, *=, /=, \=, +=, -=, &=

2.3.5.8. Precedenza generale degli operatori

Categoria
Operatori
Primario
Tutte le espressioni senza operatori
Elevamento a potenza
^
Negazione unaria
+, -
Moltiplicazione
*, /
Divisione per un numero intero
\
Modulo
Mod
Addizione
+, -
Concatenazione
&
Spostamento
<<, >>
Relazionale
=, <>, <, >, <=, >=, Like, Is, TypeOf...Is
Logico NOT
Not
AND logico
E, E anche
OR logico
OR, OrElse
XOR logico
XOR

Quando un operando è posto tra due operatori della stessa precedenza, l'associatività degli operatori determina l'ordine in cui vengono eseguite le operazioni. Tutti gli operatori sono associativi a sinistra, il che significa che le operazioni vengono eseguite da sinistra a destra. La precedenza e l'associatività possono essere controllate utilizzando espressioni tra parentesi.

2.3.5.9. Conversioni di tipo

Esistono diverse funzioni predefinite che consentono di convertire un tipo di dati in un altro. L'elenco è il seguente:

CBool,CByte,CChar,CDate,CDbl,CDec,CInt,CLng,CObj,CShort,CSng,CStr

Queste funzioni accettano come argomento un'espressione numerica o una stringa. Il tipo di risultato è indicato nella tabella seguente:

funzione
Risultato
Intervallo di valori del parametro della funzione
CBool
Booleano
Qualsiasi stringa o espressione numerica valida.
CByte
Byte
Da 0 a 255; le frazioni vengono arrotondate.
CChar
Char
Qualsiasi espressione String valida; il valore può variare da 0 a 65.535.
CDate
Data
Qualsiasi rappresentazione valida della data e dell'ora.
CDbl
Doppio
da -1,79769313486231E+308 a
-4,94065645841247E-324 per i valori negativi; da 4,94065645841247E-324 a 1,79769313486231E+308 per i valori positivi.
CDec
Decimale
+/-79.228.162.514.264.337.593.543.950.335 per i numeri non decimali. L'intervallo di valori per i numeri a 28 cifre decimali è
+/-7,9228162514264337593543950335. Il numero non nullo più piccolo è 0,0000000000000000000000000001.
CInt
Intero
Da -2.147.483.648 a 2.147.483.647; le frazioni vengono arrotondate.
CLng
Long
da -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807; le frazioni vengono arrotondate.
CObj
Oggetto
Qualsiasi espressione valida.
CShort
Short
da -32.768 a 32.767; le frazioni vengono arrotondate.
CSng
Singolo
da -3,402823E+38 a -1,401298E-45 per i valori negativi; da 1,401298E-45 a 3,402823E+38 per i valori positivi.
CStr
Stringa
I valori restituiti dalla funzione Cstr dipendono dall'argomento espressione.

Ecco un programma di esempio:


Module conversion
    Sub main()
        Dim var1 As Boolean = CBool("true")
        Dim var2 As Byte = CByte("100")
        Dim var3 As Char = CChar("A")
        Dim var4 As Date = CDate("30 janvier 2004")
        Dim var5 As Double = CDbl("100,45")
        Dim var6 As Decimal = CDec("1000,67")
        Dim var7 As Integer = CInt("-30")
        Dim var8 As Long = CLng("456")
        Dim var9 As Short = CShort("-14")
        Dim var10 As Single = CSng("56,78")
        Console.Out.WriteLine("var1=" & var1)
        Console.Out.WriteLine("var2=" & var2)
        Console.Out.WriteLine("var3=" & var3)
        Console.Out.WriteLine("var4=" & var4)
        Console.Out.WriteLine("var5=" & var5)
        Console.Out.WriteLine("var6=" & var6)
        Console.Out.WriteLine("var7=" & var7)
        Console.Out.WriteLine("var8=" & var8)
        Console.Out.WriteLine("var9=" & var9)
        Console.Out.WriteLine("var10=" & var10)
    End Sub
End Module

e i risultati della sua esecuzione:

var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78

È anche possibile utilizzare la funzione CType(espressione, tipo), come mostrato nel seguente programma:


Module ctype1
    Sub main()
        Dim var1 As Boolean = CType("true", Boolean)
        Dim var2 As Byte = CType("100", Byte)
        Dim var3 As Char = CType("A", Char)
        Dim var4 As Date = CType("30 janvier 2004", Date)
        Dim var5 As Double = CType("100,45", Double)
        Dim var6 As Decimal = CType("1000,67", Decimal)
        Dim var7 As Integer = CType("-30", Integer)
        Dim var8 As Long = CType("456", Long)
        Dim var9 As Short = CType("-14", Short)
        Dim var10 As Single = CType("56,78", Single)
        Dim var11 As String = CType("47,89", String)
        Dim var12 As String = 47.89.ToString
        Dim var13 As String = "" & 47.89
        Console.Out.WriteLine("var1=" & var1)
        Console.Out.WriteLine("var2=" & var2)
        Console.Out.WriteLine("var3=" & var3)
        Console.Out.WriteLine("var4=" & var4)
        Console.Out.WriteLine("var5=" & var5)
        Console.Out.WriteLine("var6=" & var6)
        Console.Out.WriteLine("var7=" & var7)
        Console.Out.WriteLine("var8=" & var8)
        Console.Out.WriteLine("var9=" & var9)
        Console.Out.WriteLine("var10=" & var10)
        Console.Out.WriteLine("var11=" & var11)
        Console.Out.WriteLine("var12=" & var12)
        Console.Out.WriteLine("var13=" & var13)
    End Sub
End Module

che produce i seguenti risultati:

var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78
var11=47,89
var12=47,89
var13=47,89

2.4. Istruzioni per il controllo dell'esecuzione del programma

2.4.1. Stop

Il metodo Exit definito nella classe Environment consente di interrompere l'esecuzione di un programma:


[Visual Basic]
Public Shared Sub Exit(ByVal exitCode As Integer )

interrompe il processo corrente e restituisce il valore di exitCode al processo padre. Il valore di exitCode può essere utilizzato dal processo padre. In DOS, questa variabile di stato viene restituita a DOS nella variabile di sistema ERRORLEVEL, il cui valore può essere verificato in un file batch. In Unix, la variabile $? recupera il valore di exitCode.

    Environment.Exit(0)

terminerà il programma con uno stato di uscita pari a 0.

2.4.2. Struttura decisionale semplice

if condition then
    actions_alors
else
    actions_sinon
end if
  • Ogni azione è su una riga separata
  • La clausola else può essere omessa.

È possibile nidificare le strutture decisionali come mostrato nell'esempio seguente:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
Module if1
    Sub main()
        Dim i As Integer = 10
        If i > 4 Then
            Console.Out.WriteLine(i & " est > " & 4)
        Else
            If i = 4 Then
                Console.Out.WriteLine(i & " est = " & 4)
            Else
                Console.Out.WriteLine(i & " est < " & 4)
            End If
        End If
    End Sub
End Module

Il risultato ottenuto:

10 est > 4

2.4.3. Struttura del caso

La sintassi è la seguente:

select case expression
    case liste_valeurs1
        actions1
case liste_valeurs2
        actions2
...
case else
        actions_sinon
end select
  • Il tipo di [espressione] deve essere uno dei seguenti:
Boolean, Byte, Char, Date, Decimal, Double, Integer, Long, Object, Short, Single et String
  • La clausola [case else] può essere omessa.
  • [list_of_values] sono i possibili valori dell'espressione. [lists_of_values] rappresenta un elenco di condizioni condition1, condition2, ..., conditionx. Se [expression] soddisfa una delle condizioni, vengono eseguite le azioni che seguono la clausola [list_of_values]. Le condizioni possono assumere la seguente forma:
  • val1 a val2: vero se [espressione] appartiene all'intervallo [val1,val2]
  • val1: vero se [espressione] è uguale a val1
  • is > val1: vero se [espressione] > val1. La parola chiave [is] può essere omessa
  • Lo stesso vale per gli operatori =, <, <=, >, >=, <>
  • vengono eseguite solo le azioni associate alla prima condizione verificata.

Si consideri il seguente programma:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
Module selectcase1
    Sub main()
        Dim i As Integer = 10
        Select Case i
            Case 1 To 4, 7 To 8
                Console.Out.WriteLine("i est dans l'intervalle [1,4] ou [7,8]")
            Case Is > 12
                Console.Out.WriteLine("i est > 12")
            Case Is < 15
                Console.Out.WriteLine("i est < 15")
            Case Is < 20
                Console.Out.WriteLine("i est < 20")
        End Select
    End Sub
End Module

Si ottengono i seguenti risultati:

i est < 15

2.4.4. Struttura del ciclo

2.4.4.1. Numero noto di iterazioni


For counter [ As datatype ] = start To end [ Step step ]
   actions
Next [ counter ]

Le azioni vengono eseguite per ogni valore assunto dalla variabile [contatore]. Si consideri il seguente programma:


' options
Option Explicit On 
Option Strict On

' namespaces
Imports System
 
Module for1
    Sub main()
        Dim somme As Integer = 0
        Dim résultat As String = "somme("
        For i As Integer = 0 To 10 Step 2
            somme += i
            résultat += " " + i.ToString
        Next
        résultat += ")=" + somme.ToString
        Console.Out.WriteLine(résultat)
    End Sub
End Module

I risultati:

somme( 0 2 4 6 8 10)=30

Un'altra struttura iterativa con un numero noto di iterazioni è la seguente:


For Each element [ As datatype ] In groupe
   [ actions ]
Next [ element ]
  • Un gruppo è un insieme di oggetti. L'insieme di oggetti che già conosciamo è l'array
  • Il tipo di dati è il tipo degli oggetti presenti nella raccolta. Per un array, si tratterebbe del tipo degli elementi dell'array
  • elemento è una variabile locale al ciclo che assumerà successivamente i valori della collezione.

Pertanto, il codice seguente:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
Module foreach1
    Sub main()
        Dim amis() As String = {"paul", "hélène", "jacques", "sylvie"}
        For Each nom As String In amis
            Console.Out.WriteLine(nom)
        Next
    End Sub
End Module

verrebbe visualizzato:

paul
hélène
jacques
sylvie

2.4.4.2. Numero di ripetizioni sconosciuto

In VB.NET esistono molte strutture per questo caso.


Do { While | Until } condition
   [ statements ]
Loop

Il ciclo continua finché la condizione è vera (while) o fino a quando la condizione è vera (until). Il ciclo potrebbe non essere mai eseguito.


Do
   [ statements ]
Loop { While | Until } condition

Il ciclo continua finché la condizione è vera (while) o fino a quando la condizione è vera (until). Il ciclo viene sempre eseguito almeno una volta.


While condition
   [ statements ]
End While

Il ciclo continua finché la condizione è vera. Il ciclo potrebbe non essere mai eseguito. I seguenti cicli calcolano tutti la somma dei primi 10 numeri interi.


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
Module boucles1
    Sub main()
        Dim i, somme As Integer
        i = 0 : somme = 0
        Do While i < 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do Until i = 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop Until i = 11
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop While i < 11
        Console.Out.WriteLine("somme=" + somme.ToString)
    End Sub
End Module
somme=55
somme=55
somme=55
somme=55

2.4.4.3. Istruzioni di controllo del ciclo

exit do
Esce da un ciclo do...loop
exit for
Esce da un ciclo for

2.5. La struttura di un programma VB.NET

Un programma VB.NET che non utilizza classi o funzioni definite dall'utente diverse dalla funzione principale Main può avere la seguente struttura:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports espace1
Imports ....
 
Module nomDuModule
    Sub main()
....
    End Sub
End Module
  • La direttiva [Option Explicit on] impone la dichiarazione delle variabili. In VB.NET, ciò non è obbligatorio. Una variabile non dichiarata è quindi di tipo Object.
  • La direttiva [Option Strict on] vieta qualsiasi conversione di tipo di dati che potrebbe causare la perdita di dati e qualsiasi conversione tra tipi numerici e stringhe. Le funzioni di conversione devono quindi essere utilizzate in modo esplicito.
  • Il programma importa tutti gli spazi dei nomi di cui ha bisogno. Non abbiamo ancora introdotto questo concetto. Nei programmi precedenti, abbiamo spesso incontrato istruzioni come:
        Console.Out.WriteLine(unechaine)

In realtà avremmo dovuto scrivere:

        System.Console.Out.WriteLine(unechaine)

dove System è lo spazio dei nomi contenente la classe [Console]. Importando lo spazio dei nomi [System] con un'istruzione Imports, VB.NET lo cercherà sistematicamente ogni volta che incontra una classe che non riconosce. Ripeterà la ricerca in tutti gli spazi dei nomi dichiarati fino a quando non troverà la classe in questione. Scriviamo quindi:


' namespaces
Imports System
....
 
        Console.Out.WriteLine(unechaine)

Un programma di esempio potrebbe essere simile al seguente:


' options
Option Explicit On 
Option Strict On
 
'namespaces
Imports System
 
' main module
Module main1
    Sub main()
        Console.Out.WriteLine("main1")
    End Sub
End Module

Lo stesso programma può essere scritto come segue:


' options
Option Explicit On 
Option Strict On
 
'namespaces
Imports System
 
' test class
Public Class main2
    Public Shared Sub main()
        Console.Out.WriteLine("main2")
    End Sub
End Class

Qui stiamo utilizzando il concetto di classe, che verrà introdotto nel prossimo capitolo. Quando una classe di questo tipo contiene una procedura statica (condivisa) denominata main, questa viene eseguita. Includiamo questo codice qui perché C#, il linguaggio gemello di VB.NET, riconosce solo il concetto di classe, ovvero tutto il codice eseguito deve appartenere a una classe. Il concetto di classe fa parte della programmazione orientata agli oggetti. Imporlo nella progettazione di ogni programma è un po' scomodo. Lo vediamo qui nella versione 2 del programma precedente, dove siamo costretti a introdurre i concetti di classi e metodi statici dove non sono necessari. Pertanto, d'ora in poi, introdurremo il concetto di classe solo quando sarà necessario. Negli altri casi, useremo il concetto di modulo, come nella versione 1 sopra.

2.6. Compilazione ed esecuzione di un programma VB.NET

Per compilare un programma VB.NET è necessario solo l'SDK .NET. Consideriamo il seguente programma:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
Module boucles1
    Sub main()
        Dim i, somme As Integer
        i = 0 : somme = 0
        Do While i < 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do Until i = 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop Until i = 11
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop While i < 11
        Console.Out.WriteLine("somme=" + somme.ToString)
    End Sub
End Module

Supponiamo che si trovi in un file chiamato [loops1.vb]. Per compilarlo, procediamo come segue:

dos>dir boucles1.vb
11/03/2004  15:55                  583 boucles1.vb

dos>vbc boucles1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.

dos>dir boucles1.*
11/03/2004  16:04                  601 boucles1.vb
11/03/2004  16:04                3 584 boucles1.exe

Il programma vbc.exe è il compilatore VB.NET. In questo caso, si trovava nel PATH di DOS:


dos>path
PATH=E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE;E:\Program Files\Microsoft Visual Studio .NET 2003\VC7\BIN;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin\prerelease;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin;E:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;E:\WINNT\Microsoft.NET\Framework\v1.1.4322;e:\winnt\system32;e:\winnt;

dos>dir E:\WINNT\Microsoft.NET\Framework\v1.1.4322\vbc.exe
21/02/2003  10:20              737 280 vbc.exe

Il compilatore [vbc] produce un file .exe che può essere eseguito dalla macchina virtuale .NET:

dos>boucles1
somme=55
somme=55
somme=55
somme=55

2.7. Esempio di calcolo delle imposte

Proponiamo di scrivere un programma per calcolare l'imposta di un contribuente. Consideriamo il caso semplificato di un contribuente che deve dichiarare solo il proprio stipendio:

  • calcoliamo il numero di scaglioni fiscali per il dipendente come nbParts = nbEnfants / 2 + 1 se è celibe, e nbEnfants / 2 + 2 se è coniugato, dove nbEnfants è il numero di figli.
  • se ha almeno tre figli, riceve una quota aggiuntiva pari a metà
  • Calcoliamo il suo reddito imponibile R = 0,72 * S, dove S è il suo stipendio annuale
  • Calcoliamo il suo coefficiente familiare QF = R / nbParts
  • calcoliamo la sua imposta I. Consideriamo la seguente tabella:
12620,0
0
0
13.190
0,05
631
15.640
0,1
1.290,5
24.740
0,15
2.072,5
31.810
0,2
3.309,5
39.970
0,25
4900
48.360
0,3
6.898,5
55.790
0,35
9.316,5
92.970
0,4
12.106
127.860
0,45
16.754,5
151.250
0,50
23.147,5
172.040
0,55
30.710
195.000
0,60
39.312
0
0,65
49062

Ogni riga ha 3 campi. Per calcolare l'imposta I, trova la prima riga in cui QF <= campo1. Ad esempio, se QF = 23.000, la riga trovata sarà

    24740        0.15        2072.5

L'imposta I è quindi pari a 0,15*R - 2072,5*nbParts. Se QF è tale che la condizione QF<=field1 non è mai soddisfatta, vengono utilizzati i coefficienti dell'ultima riga. Qui:

    0                0.65        49062

il che dà come risultato l'imposta I = 0,65*R - 49062*nbParts. Il programma VB.NET corrispondente è il seguente:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
Module impots
    ' ------------ hand
    Sub Main()
 
        ' data tables required for tax calculation
        Dim Limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
        Dim CoeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}
 
        ' we recover marital status
        Dim OK As Boolean = False
        Dim reponse As String = Nothing
        While Not OK
            Console.Out.Write("Etes-vous marié(e) (O/N) ? ")
            reponse = Console.In.ReadLine().Trim().ToLower()
            If reponse <> "o" And reponse <> "n" Then
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            Else
                OK = True
            End If
        End While
        Dim Marie As Boolean = reponse = "o"
 
        ' number of children
        OK = False
        Dim NbEnfants As Integer = 0
        While Not OK
            Console.Out.Write("Nombre d'enfants : ")
            reponse = Console.In.ReadLine()
            Try
                NbEnfants = Integer.Parse(reponse)
                If NbEnfants >= 0 Then
                    OK = True
                Else
                    Console.Error.WriteLine("Réponse incorrecte. Recommencez")
                End If
            Catch
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            End Try
        End While
        ' salary
        OK = False
        Dim Salaire As Integer = 0
        While Not OK
            Console.Out.Write("Salaire annuel : ")
            reponse = Console.In.ReadLine()
            Try
                Salaire = Integer.Parse(reponse)
                If Salaire >= 0 Then
                    OK = True
                Else
                    Console.Error.WriteLine("Réponse incorrecte. Recommencez")
                End If
            Catch
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            End Try
        End While
        ' calculating the number of shares
        Dim NbParts As Decimal
        If Marie Then
            NbParts = CDec(NbEnfants) / 2 + 2
        Else
            NbParts = CDec(NbEnfants) / 2 + 1
        End If
        If NbEnfants >= 3 Then
            NbParts += 0.5D
        End If
        ' taxable income
        Dim Revenu As Decimal
        Revenu = 0.72D * Salaire
 
        ' family quotient
        Dim QF As Decimal
        QF = Revenu / NbParts
 
        ' search for tax bracket corresponding to QF
        Dim i As Integer
        Dim NbTranches As Integer = Limites.Length
        Limites((NbTranches - 1)) = QF
        i = 0
        While QF > Limites(i)
            i += 1
        End While
        ' tax
        Dim impots As Integer = CInt(i * 0.05D * Revenu - CoeffN(i) * NbParts)
 
        ' the result is displayed
        Console.Out.WriteLine(("Impôt à payer : " & impots))
    End Sub
End Module

Il programma viene compilato in una finestra DOS utilizzando:

dos>vbc impots1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573

dos>dir impots1.exe
24/02/2004  15:42                5 632 impots1.exe

La compilazione produce un file eseguibile denominato impots.exe. Si noti che impots.exe non è direttamente eseguibile dal processore. In realtà contiene codice intermedio eseguibile solo su una piattaforma .NET. I risultati ottenuti sono i seguenti:

dos>impots1
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : 3
Salaire annuel : 200000
Impôt à payer : 16400
dos>impots1
Etes-vous marié(e) (O/N) ? n
Nombre d'enfants : 2
Salaire annuel : 200000
Impôt à payer : 33388
dos>impots1
Etes-vous marié(e) (O/N) ? w
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? q
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : q
Réponse incorrecte. Recommencez
Nombre d'enfants : 2
Salaire annuel : q
Réponse incorrecte. Recommencez
Salaire annuel : 1
Impôt à payer : 0

2.8. Argomenti principali del programma

La procedura principale Main può accettare un array di stringhe come parametro:


    Sub main(ByVal args() As String)

Il parametro args è un array di stringhe che riceve gli argomenti passati sulla riga di comando quando viene richiamato il programma.

  • args.Length è il numero di elementi nell'array args
  • args(i) è l'i-esimo elemento dell'array

Se eseguiamo il programma P con il comando: P arg0 arg1 … argn e se la procedura Main del programma P è dichiarata come segue:


    Sub main(ByVal args() As String)

avremo arg(0)="arg0", arg(1)="arg1" … Ecco un esempio:


' guidelines
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
 
Module arg
    Sub main(ByVal args() As String)
        ' number of arguments
        console.out.writeline("Il y a " & args.length & " arguments")
        Dim i As Integer
        For i = 0 To args.Length - 1
            Console.Out.WriteLine("argument n° " & i & "=" & args(i))
        Next
    End Sub
End Module

L'esecuzione produce i seguenti risultati:

dos>arg1 a b c
Il y a 3 arguments
argument n° 0=a
argument n° 1=b
argument n° 2=c

2.9. Enumerazioni

Un'enumerazione è un tipo di dati il cui dominio dei valori è un insieme di costanti intere. Consideriamo un programma che deve gestire i voti degli esami. Ce ne sarebbero cinque: Promosso, Discreto, Buono, Ottimo, Eccellente. Potremmo quindi definire un'enumerazione per queste cinque costanti:


    Enum mention
        Passable
        AssezBien
        Bien
        TrésBien
        Excellent
    End Enum

Internamente, queste cinque costanti sono rappresentate da numeri interi consecutivi che iniziano con 0 per la prima costante, 1 per la successiva e così via. È possibile dichiarare una variabile in modo che assuma questi valori nell'enumerazione:


        ' a variable that takes its values from the enumeration mentioned
        Dim maMention As mention = mention.Passable

Una variabile può essere confrontata con i diversi valori possibili dell'enumerazione:


        ' test avec valeur de l'énumération
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If

È possibile recuperare tutti i valori dell'enumerazione:


        For Each m In mention.GetValues(maMention.GetType)
            Console.Out.WriteLine(m)
        Next

Proprio come il tipo semplice Integer è equivalente alla struttura Int32, il tipo semplice Enum è equivalente alla struttura Enum. Questa classe dispone di un metodo statico GetValues che consente di recuperare tutti i valori di un tipo enumerato passato come parametro. Questo parametro deve essere un oggetto di tipo Type, ovvero una classe che fornisce informazioni su un tipo di dati. Il tipo di una variabile v si ottiene tramite v.GetType(). Quindi, in questo caso, maMention.GetType() restituisce l'oggetto Type per l'enumerazione mentions, mentre Enum.GetValues(maMention.GetType()) restituisce l'elenco dei valori per l'enumerazione mentions.

Questo è ciò che dimostra il seguente programma:


' guidelines
Option Strict On
Option Explicit On 
 
' namespaces
Imports System

Public Module enum2
 
    ' an enumeration
    Enum mention
        Passable
        AssezBien
        Bien
        TrèsBien
        Excellent
    End Enum
 
    ' test pg
    Sub Main()
 
        ' a variable that takes its values from the enumeration mentioned
        Dim maMention As mention = mention.Passable
 
        ' variable value display
        Console.Out.WriteLine("mention=" & maMention)
 
        ' test with enumeration value
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If
 
        ' list of literal mentions
        For Each m As mention In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m.ToString)
        Next
 
        ' list of full mentions
        For Each m As Integer In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m)
        Next
    End Sub
End Module

I risultati dell'esecuzione sono i seguenti:

dos>enum2
mention=0
Peut mieux faire
Passable
AssezBien
Bien
TrèsBien
Excellent
0
1
2
3
4

2.10. Gestione delle eccezioni

Molte funzioni VB.NET sono in grado di generare eccezioni, ovvero errori. Quando una funzione è in grado di generare un'eccezione, il programmatore dovrebbe gestirla al fine di creare programmi più resistenti agli errori: si dovrebbe sempre evitare che un'applicazione si "blocchi" in modo imprevisto.

La gestione delle eccezioni segue questo schema:

try
    appel de la fonction susceptible de générer l'exception
catch  e as Exception e)
    traiter l'exception e
end try
instruction suivante

Se la funzione non genera un'eccezione, il programma procede all'istruzione successiva; in caso contrario, entra nel corpo della clausola catch e poi procede all'istruzione successiva. Si notino i seguenti punti:

  • e è un oggetto derivato dal tipo Exception. Possiamo essere più specifici utilizzando tipi come IOException, SystemException, ecc.: esistono diversi tipi di eccezioni. Scrivendo catch e come Exception, indichiamo che vogliamo gestire tutti i tipi di eccezioni. Se il codice nel blocco try è suscettibile di generare più tipi di eccezioni, potremmo voler essere più specifici gestendo l'eccezione con più blocchi catch:
try
    appel de la fonction susceptible de générer l'exception
catch e as IOException 
    traiter l'exception e
catch  e as SystemException
    traiter l'exception e
end try
instruction suivante
  • È possibile aggiungere una clausola finally ai blocchi try/catch:
try
    appel de la fonction susceptible de générer l'exception
catch  e as Exception
    traiter l'exception e
finally
    code exécuté après try ou catch
end try
instruction suivante

Indipendentemente dal fatto che si verifichi o meno un'eccezione, il codice nella clausola finally verrà sempre eseguito.

  • Nella clausola catch, potresti non voler utilizzare l'oggetto Exception disponibile. Invece di scrivere catch e come Exception, scrivi catch.
  • La classe Exception dispone di una proprietà Message che contiene un messaggio che descrive in dettaglio l'errore verificatosi. Pertanto, se si desidera visualizzare questo messaggio, si scriverà:
catch e as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+e.Message);
    ...
end try
  • La classe Exception dispone di un metodo ToString che restituisce una stringa indicante il tipo di eccezione e il valore della proprietà Message. Possiamo quindi scrivere:
catch  ex as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+ex.ToString)
    ...
end try

L'esempio seguente mostra un'eccezione generata dall'utilizzo di un elemento di array inesistente:


' options
Option Explicit On 
Option Strict On
 
' namespaces
Imports System
 
Module tab1
    Sub Main()
        ' declaring & initializing an array
        Dim tab() As Integer = {0, 1, 2, 3}
        Dim i As Integer
 
        ' table display with for
        For i = 0 To tab.Length - 1
            Console.Out.WriteLine(("tab[" & i & "]=" & tab(i)))
        Next i
 
        ' table display with a for each
        Dim élmt As Integer
        For Each élmt In tab
            Console.Out.WriteLine(élmt)
        Next élmt
 
        ' generating an exception
        Try
            tab(100) = 6
        Catch e As Exception
            Console.Error.WriteLine(("L'erreur suivante s'est produite : " & e.Message))
        End Try
    End Sub
End Module

L'esecuzione del programma produce i seguenti risultati:

dos>exception1
tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
0
1
2
3
L'erreur suivante s'est produite : L'index se trouve en dehors des limites du tableau.

Ecco un altro esempio in cui gestiamo l'eccezione causata dall'assegnazione di una stringa a un numero quando la stringa non rappresenta un numero:


' options
Option Strict On
Option Explicit On 
 
'imports
Imports System
 
Public Module console1
  Public Sub Main()
    ' We ask for the name
    System.Console.Write("Nom : ")
 
        ' reading response
    Dim nom As String = System.Console.ReadLine()
 
        ' age requested
    Dim age As Integer
    Dim ageOK As Boolean = False
    Do While Not ageOK
      ' question
      Console.Out.Write("âge : ")
      ' reading-checking response
      Try
        age = Int32.Parse(System.Console.ReadLine())
        If age < 0 Then Throw New Exception
        ageOK = True
      Catch
        Console.Error.WriteLine("Age incorrect, recommencez...")
      End Try
    Loop
 
        ' final display
    Console.Out.WriteLine("Vous vous appelez [" & nom & "] et vous avez [" & age & "] ans")
  End Sub
End Module

Alcuni risultati dell'esecuzione:

dos>console1
Nom : dupont
âge : 23
Vous vous appelez dupont et vous avez 23 ans
dos>console1
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12 ans

2.11. Passaggio dei parametri a una funzione

Qui ci interessa capire come vengono passati i parametri a una funzione. Consideriamo la funzione:


    Sub changeInt(ByVal a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub    

Nella definizione della funzione, a è chiamato parametro formale. È presente esclusivamente allo scopo di definire la funzione changeInt. Avrebbe potuto tranquillamente chiamarsi b. Consideriamo ora un esempio di utilizzo di questa funzione:


    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub

Qui, nell'istruzione changeInt(age), age è il parametro effettivo che passerà il proprio valore al parametro formale a. Ci interessa capire come un parametro formale recuperi il valore del corrispondente parametro effettivo.

2.11.1. Passaggio per valore

L'esempio seguente mostra che i parametri di una funzione/procedura vengono passati per valore per impostazione predefinita: ovvero, il valore del parametro effettivo viene copiato nel parametro formale corrispondente. Si tratta di due entità distinte. Se la funzione modifica il parametro formale, il parametro effettivo rimane invariato.


' options
Option Explicit On 
Option Strict On
 
' passing parameters by value to a function
Imports System
 
Module param1
    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub
 
    Sub changeInt(ByVal a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub
End Module

I risultati sono i seguenti:

Paramètre formel a=30
Paramètre effectif age=20

Il valore 20 del parametro effettivo è stato copiato nel parametro formale a. Il parametro formale è stato quindi modificato. Il parametro effettivo è rimasto invariato. Questa modalità di passaggio è adatta per i parametri di input di una funzione.

2.11.2. Passaggio per riferimento

In un passaggio per riferimento, il parametro effettivo e il parametro formale sono la stessa entità. Se la funzione modifica il parametro formale, viene modificato anche il parametro effettivo. In VB.NET, il parametro formale deve essere preceduto dalla parola chiave ByRef. Ecco un esempio:


' options
Option Explicit On 
Option Strict On
 
' passing parameters by value to a function
Imports System
 
Module param2
    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub
 
    Sub changeInt(ByRef a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub
End Module

e i risultati dell'esecuzione:

Paramètre formel a=30
Paramètre effectif age=30

Il parametro effettivo ha seguito la modifica del parametro formale. Questa modalità di passaggio è adatta per i parametri di output di una funzione.