通过值和通过引用传递参数 (Visual Basic)

在 Visual Basic 中,可以将实参通过值或通过引用传递给过程。 这称为传递机制,它确定过程是否更改调用代码中作为实参基础的编程元素。 过程声明通过指定 ByVal (Visual Basic)ByRef (Visual Basic) 关键字确定每个形参的传递机制。

差异

将实参传递给过程时,请注意它们互相影响的几点差异:

  • 基础编程元素可更改还是不可更改

  • 实参本身可更改还是不可更改

  • 实参通过值还是通过引用传递

  • 实参数据类型是值类型还是引用类型

有关更多信息,请参见可修改和不可修改参数之间的差异 (Visual Basic)通过值传递参数和通过引用传递参数之间的差异 (Visual Basic)

选择传递机制

应该认真选择每个实参的传递机制。

  • 保护。 在两个传递机制之间选择时,最重要的标准是公开要更改的调用变量。 传递实参 ByRef 的优点是过程可以通过该实参将值返回给调用代码。 传递实参 ByVal 的优点是它可防止变量被过程更改。

  • 性能。 尽管传递机制能够影响代码的性能,但差异通常并不显著。 这种情况的一个例外是被传递给 ByVal 的值类型。 这种情况下,Visual Basic 会复制实参的整个数据内容。 因此,对于像结构这样的大值类型,以 ByRef 传递机制传递实参的效率可能更高。

    对于引用类型,仅复制指向数据的指针(32 位平台采用四个字节,64 位平台采用八个字节)。 因此,可以通过值传递 String 或 Object 类型的实参而不会降低性能。

确定传递机制

过程声明指定每个形参的传递机制。 调用代码无法重写 ByVal 结构。

如果参数声明 ByRef,调用代码可以强制该结构到 ByVal 通过将实参名称括号中调用。 有关更多信息,请参见如何:强制通过值传递参数 (Visual Basic)

Visual Basic 中的默认行为是通过值传递实参。

何时通过值传递实参

  • 如果作为实参基础的调用代码元素是不可更改元素,则以 ByVal (Visual Basic) 声明对应的形参。 任何代码都不能更改不可更改元素的值。

  • 如果基础元素可更改,但您不想让过程更改它的值,则以 ByVal 声明形参。 只有调用代码可以更改通过值传递的可更改元素的值。

何时通过引用传递实参

  • 如果过程确实需要更改调用代码中的基础元素,则以 ByRef (Visual Basic) 声明对应的形参。

  • 如果正确执行代码取决于更改调用代码中基础元素的过程,则以 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

请参见

任务

如何:将参数传递给过程 (Visual Basic)

如何:更改过程参数的值 (Visual Basic)

如何:防止过程参数的值被更改 (Visual Basic)

如何:强制通过值传递参数 (Visual Basic)

概念

Visual Basic 中的过程

过程参数和变量 (Visual Basic)

按位置和名称传递参数 (Visual Basic)

值类型和引用类型