Oppure

Loading

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  



A cura di: Il Totem