以傳值和傳址方式傳遞引數 (Visual Basic)
在 Visual Basic 中,您可以傳值或傳址方式將引數傳遞至程序。 這稱為傳遞機制,此機制會判斷程序是否可以修改呼叫程式碼中作為引數基礎的程式設計項目。 程序宣告會藉由指定 ByVal 或 ByRef 關鍵字,判斷每個參數的傳遞機制。
區別
將引數傳遞至程序時,請注意幾個互相影響的不同差異:
基礎程式設計項目屬於可修改還是不可修改
引數本身屬於可修改還是不可修改
引數是以傳值還是傳址方式傳遞
引數資料類型屬於實值型別還是參考型別
如需詳細資訊,請參閱可修改引數與不可修改引數之間的差異,以及以傳值或傳址方式傳遞引數的差別。
選擇傳遞機制
您應該為每個引數謹慎選擇傳遞機制。
保護。 在兩種傳遞機制之間進行選擇時,最重要的準則是呼叫變數發生變化的暴露。 傳遞
ByRef
引數的優點是程序可以透過該引數將值傳回呼叫程式碼。 傳遞ByVal
引數的優點是其會保護變數不受程序變更。效能: 儘管傳遞機制可能會影響程式碼效能,但差異通常微乎其微。 其中一個例外狀況是傳遞
ByVal
的實值型別。 在此情況下,Visual Basic 會複製引數的整個資料內容。 因此,對於結構等大型實值型別而言,將ByRef
傳遞給它會更有效率。針對參考型別,僅複製資料的指標 (在 32 位元平台上為四個位元組,在 64 位元平台上為八個位元組)。 因此,您可以傳值方式傳遞
String
或Object
類型引數,而不會損害效能。
決定傳遞機制
程序宣告會指定每個參數的傳遞機制。 呼叫程式碼無法覆寫 ByVal
機制。
如果使用 ByRef
宣告參數,則呼叫程式碼可以在呼叫中將引數名稱括在括號中,藉此強制 ByVal
機制。 如需詳細資訊,請參閱如何:強制以傳值方式傳遞引數。
Visual Basic 中的預設值是以傳值方式傳遞引數。
以傳值方式傳遞引數的時機
如果作為引數基礎的呼叫程式碼項目屬於不可修改項目,請宣告對應的參數 ByVal。 沒有程式碼可以變更不可修改項目的值。
如果基礎項目是可修改的,但您不希望程序能夠變更其值,請宣告
ByVal
參數。 只有呼叫端程式碼可以變更以傳值方式傳遞的可修改項目值。
以傳址方式傳遞引數的時機
如果程序確實需要變更呼叫程式碼中的基礎項目,請宣告對應的參數 ByRef。
如果正確執行程式碼須取決於變更呼叫程式碼中基礎項目的程序,請宣告
ByRef
參數。 如果您以傳值方式進行傳遞,或呼叫程式碼將引數括住括號中來覆寫ByRef
傳遞機制,則程序呼叫可能會產生非預期結果。
範例
描述
下列範例說明何時該以傳值方式傳遞引數,而何時該以傳址方式傳遞引數。 Calculate
程序同時具有 ByVal
和 ByRef
參數。 假設利率為 rate
且現金總額為 debt
,程序的工作是計算 debt
的新值,這是將利率套用至 debt
原始值的結果。 由於 debt
是 ByRef
參數,因此新的總數會反映在對應至 debt
的呼叫程式碼的引數值。 rate
參數是 ByVal
參數,因為 Calculate
不應該變更其值。
程式碼
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