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 ModuleCome 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
A cura di: Il Totem