|
Parametri opzionali
Come suggerisce il nome stesso, i parametri opzionali sono speciali parametri che non è obbligatorio specificare quando si invoca
un metodo. Li si dichiara facendo precedere la clausola ByVal o ByRef dalla keyword Optional: inoltre, dato che un parametro del genere
può anche essere omesso, bisogna necessariamente indicare un valore predefinito che esso possa assumere. Tale valore predefinito deve
essere una costante e, per questo motivo, se ricordate il discorso precedentemente fatto sull'assegnamento delle costanti, i parametri
opzionali possono essere solo di tipo base. Ecco un esempio:
Module Module1
'Disegna una barra "di caricamento" animata con dei trattini
'e dei pipe (|). Length indica la sua lunghezza, ossia quanti
'caratterei debbano essere stampati a schermo. AnimationSpeed
'è la velocità dell'animazione, di default 1
Sub DrawBar(ByVal Length As Int32, _
Optional ByVal AnimationSpeed As Single = 1)
'La variabile static tiene conto del punto a cui si è
'arrivati al caricamento
Static Index As Int32 = 1
'Disegna la barra
For I As Int32 = 1 To Length
If I > Index Then
Console.Write("-")
Else
Console.Write("|")
End If
Next
'Aumenta l'indice di uno. Notare il particolare
'assegnamento che utilizza l'operatore Mod. Finché
'Index è minore di Length, questa espressione equivale
'banalmente a Index + 1, poiché a Mod b = a se a < b.
'Quando Index supera il valore di Length, allora l'operatore
'Mod cambia le cose: infatti, se Index = Length + 1,
'l'espressione restituisce 0, che, sommato a 1, dà 1.
'Il risultato che otteniamo è che Index reinizia
'da capo, da 1 fino a Length.
Index = (Index Mod (Length + 1)) + 1
'Il metodo Sleep, che vedremo approfonditamente solo nella
'sezione B, fa attendere al programma un certo numero di
'millisecondi.
'1000 / AnimationSpeed provoca una diminuzione del tempo
'di attesa all'aumentare della velocità
Threading.Thread.CurrentThread.Sleep(1000 / AnimationSpeed)
End Sub
Sub Main()
'Disegna la barra con un ciclo infinito. Potete invocare
'DrawBar(20) tralasciando l'ultimo argomento e l'animazione
'sarà lenta poiché la velocità di default è 1
Do
Console.Clear()
DrawBar(20, 5)
Loop
End Sub
End Module
Parametri indefiniti
Questo particolare tipo di parametri non rappresenta un solo elemento, ma bensì una collezione di elementi: infatti, si specifica un
parametro come indefinito quando non si sa a priori quanti parametri il metodo richiederà. A sostegno di questo fatto, i parametri indefiniti
sono dichiarati come array, usando la keyword ParamArray interposta tra la clausola ByVal o ByRef e il nome del parametro.
Module Module1
'Somma tutti i valori passati come parametri.
Function Sum(ByVal ParamArray Values() As Single) As Single
Dim Result As Single = 0
For I As Int32 = 0 To Values.Length - 1
Result += Values(I)
Next
Return Result
End Function
Sub Main()
Dim S As Single
'Somma due valori
S = Sum(1, 2)
'Somma quattro valori
S = Sum(1.1, 5.6, 98.2, 23)
'Somma un array di valori
Dim V() As Single = {1, 8, 3.4}
S = Sum(V)
End Sub
End Module
Come si vede, mediante ParamArray, la funzione diventa capace si accettare sia una lista di valori specificata dal programmatore si un
array di valori, dato che il parametro indefinito, in fondo, è pur sempre un array. N.B.: può esistere uno e un solo parametro dichiarato con ParamArray per ciascun metodo, ed esso deve sempre essere posto
alla fine dell'elenco dei parametri. Esempio:
Module Module1
'Questa funzione calcola un prezzo includendovi anche
'il pagamento di alcune tasse (non sono un esperto di
'economia, perciò mi mantengono piuttosto sul vago XD).
'Il primo parametro rappresenta il prezzo originale, mentre
'il secondo è un parametro indefinito che
'raggruppa tutte le varie tasse vigenti sul prodotto
'da acquistare che devono essere aggiunte all'importo
'iniziale (espresse come percentuali)
Function ApplyTaxes(ByVal OriginalPrice As Single, _
ByVal ParamArray Taxes() As Single) As Single
Dim Result As Single = OriginalPrice
For Each Tax As Single In Taxes
Result += OriginalPrice * Tax / 100
Next
Return Result
End Function
Sub Main()
Dim Price As Single = 120
'Aggiunge una tassa del 5% a Price
Dim Price2 As Single = _
ApplyTaxes(Price, 5)
'Aggiunge una tassa del 5%, una del 12.5% e una
'dell'1% a Price
Dim Price3 As Single = _
ApplyTaxes(Price, 5, 12.5, 1)
Console.WriteLine("Prezzo originale: " & Price)
Console.WriteLine("Presso con tassa 1: " & Price2)
Console.WriteLine("Prezzo con tassa 1, 2 e 3: " & Price3)
Console.ReadKey()
End Sub
End Module
Ricorsione
Si ha una situazione di ricorsione quando un metodo invoca se stesso: in questi casi, il metodo viene detto ricorsivo. Tale tecnica possiede
pregi e difetti: il pregio principale consiste nella riduzione drastica del codice scritto, con un conseguente aumento della leggibilità;
il difetto più rilevante è l'uso spropositato di memoria, per evitare il quale è necessario adottare alcune
tecniche di programmazione dinamica. La ricorsione, se male usata, inoltre, può facilmente provocare il crash di un'applicazione
a causa di un overflow dello stack. Infatti, se un metodo continua indiscriminatamente a invocare se stesso, senza alcun controllo per potersi
fermare (o con costrutti di controllo contenenti errori logici), continua anche a richiedere nuova memoria per il passaggio dei parametri
e per le variabili locali, oltre che per l'invocazione stessa: tutte queste richieste finiscono per sovraccaricare la memoria temporanea, che,
non riuscendo più a soddisfarle, le deve rifiutare, provocando il suddetto crash. Ma forse sono troppo pessimista: non vorrei che
rinunciaste ad usare la ricorsione per paura di incorrere in tutti questi spauracchi: ci sono certi casi in cui è davvero utile.
Come esempio non posso che presentare il classico calcolo del fattoriale:
Module Module1
'Notare che il parametro è di tipo Byte perchè il
'fattoriale cresce in modo abnorme e già a 170! Double non
'basta più a contenere il risultato
Function Factorial(ByVal N As Byte) As Double
If N <= 1 Then
Return 1
Else
Return N * Factorial(N - 1)
End If
End Function
Sub Main()
Dim Number As Byte
Console.WriteLine("Inserisci un numero (0 <= x < 256):")
Number = Console.ReadLine
Console.WriteLine(Number & "! = " & Factorial(Number))
Console.ReadKey()
End Sub
End Module
|
|