Passaggio di argomenti per valore e per riferimento (Visual Basic)

In Visual Basic è possibile passare un argomento a una routine per valore o per riferimento. Questa operazione è nota come meccanismo di passaggio e determina se la routine può modificare l'elemento di programmazione sottostante l'argomento nel codice chiamante. La dichiarazione di routine determina il meccanismo di passaggio per ogni parametro specificando la parola chiave ByVal o ByRef.

Distinzioni

Quando si passa un argomento a una routine, tenere presente diverse distinzioni che interagiscono tra loro:

  • Indica se l'elemento di programmazione sottostante è modificabile o non modificabile

  • Indica se l'argomento stesso è modificabile o non modificabile

  • Indica se l'argomento viene passato per valore o per riferimento

  • Indica se il tipo di dati dell'argomento è un tipo valore o un tipo riferimento

Per altre informazioni, vedere Differenze tra argomenti modificabili e non modificabili e Differenze tra il passaggio di un argomento per valore e per riferimento.

Scelta del meccanismo di passaggio

È consigliabile scegliere attentamente il meccanismo di passaggio per ogni argomento.

  • Protezione. Nella scelta tra i due meccanismi di passaggio, il criterio più importante è l'esposizione delle variabili chiamanti da modificare. Il vantaggio di passare un argomento ByRef sta nel fatto che la routine può restituire un valore al codice chiamante tramite tale argomento. Il vantaggio di passare un argomento ByVal sta nel fatto che protegge una variabile dalla modifica da parte della routine.

  • Prestazioni. Anche se il meccanismo di passaggio può influire sulle prestazioni del codice, la differenza è in genere insignificante. Un'eccezione a quanto indicato è un tipo di valore passato ByVal. In questo caso, Visual Basic copia l'intero contenuto dei dati dell'argomento. Di conseguenza, per un tipo di valore di grandi dimensioni, ad esempio una struttura, può essere più efficiente usare un passaggio ByRef.

    Per i tipi di riferimento, viene copiato solo il puntatore ai dati (quattro byte nelle piattaforme a 32 bit, otto byte nelle piattaforme a 64 bit). Pertanto, è possibile passare argomenti di tipo String o Object per valore senza danneggiare le prestazioni.

Determinazione del meccanismo di passaggio

La dichiarazione di routine specifica il meccanismo di passaggio per ogni parametro. Il codice chiamante non può eseguire l'override di un meccanismo ByVal.

Se un parametro viene dichiarato con ByRef, il codice chiamante può forzare l'applicazione del meccanismo ByVal racchiudendo il nome dell'argomento tra parentesi nella chiamata. Per altre informazioni, vedere Procedura: Forzare il passaggio di un argomento per valore.

Il valore predefinito in Visual Basic prevede il passaggio degli argomenti per valore.

Quando passare un argomento per valore

  • Se l'elemento del codice chiamante sottostante l'argomento è un elemento non modificabile, dichiarare il parametro ByVal corrispondente. Nessun codice può modificare il valore di un elemento non modificabile.

  • Se l'elemento sottostante è modificabile, ma non si vuole che la routine possa modificarne il valore, dichiarare il parametro ByVal. Solo il codice chiamante può modificare il valore di un elemento modificabile passato per valore.

Quando passare un argomento per riferimento

  • Se la routine deve modificare l'elemento sottostante nel codice chiamante, dichiarare il parametro ByRef corrispondente.

  • Se la corretta esecuzione del codice dipende dalla modifica dell'elemento sottostante nel codice chiamante da parte della routine, dichiarare il parametro ByRef. Se viene passato per valore o se il codice chiamante esegue l'override del meccanismo di passaggio ByRef racchiudendo l'argomento tra parentesi, la chiamata di routine potrebbe generare risultati imprevisti.

Esempio

Descrizione

Nell'esempio seguente viene illustrato quando passare argomenti per valore e quando passarli per riferimento. La routine Calculate ha sia un parametro ByVal sia un parametro ByRef. Dato un tasso di interesse, rate, e una somma di denaro, debt, l'attività della routine consiste nel calcolare un nuovo valore per debt che è il risultato dell'applicazione del tasso di interesse al valore originale di debt. Poiché debt è un parametro ByRef, il nuovo totale si riflette nel valore dell'argomento nel codice chiamante che corrisponde a debt. Il parametro rate è un parametro ByVal perché Calculate non deve modificarne il valore.

Codice

Module Module1

    Sub Main()
        ' Two interest rates are declared, one a constant and one a 
        ' variable.
        Const highRate As Double = 12.5
        Dim lowRate = highRate * 0.6

        Dim initialDebt = 4999.99
        ' Make a copy of the original value of the debt.
        Dim debtWithInterest = initialDebt

        ' Calculate the total debt with the high interest rate applied.
        ' Argument highRate is a constant, which is appropriate for a 
        ' ByVal parameter. Argument debtWithInterest must be a variable
        ' because the procedure will change its value to the calculated
        ' total with interest applied.
        Calculate(highRate, debtWithInterest)
        ' Format the result to represent currency, and display it.
        Dim debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with high interest: " & debtString)

        ' Repeat the process with lowRate. Argument lowRate is not a 
        ' constant, but the ByVal parameter protects it from accidental
        ' or intentional change by the procedure. 

        ' Set debtWithInterest back to the original value.
        debtWithInterest = initialDebt
        Calculate(lowRate, debtWithInterest)
        debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with low interest:  " & debtString)
    End Sub

    ' Parameter rate is a ByVal parameter because the procedure should
    ' not change the value of the corresponding argument in the 
    ' calling code. 

    ' The calculated value of the debt parameter, however, should be
    ' reflected in the value of the corresponding argument in the 
    ' calling code. Therefore, it must be declared ByRef. 
    Sub Calculate(ByVal rate As Double, ByRef debt As Double)
        debt = debt + (debt * rate / 100)
    End Sub

End Module

Vedi anche