【问题标题】:ByVal in Excel event-handlerExcel 事件处理程序中的 ByVal
【发布时间】:2019-07-26 17:26:02
【问题描述】:

我对在 Excel 的某些事件处理程序中使用 ByVal 关键字感到有些困惑。

NewSheet 事件示例 (复制自 Excel 2019 Power Programming with VBA,Wiley)

Private Sub Workbook_NewSheet(ByVal Sh As Object)
    If TypeName(Sh) = "Worksheet" Then
        Sh.Cells.ColumnWidth = 35
        Sh.Range("A1") = "Sheet added " & Now()
    End If
End Sub

此代码按预期工作,似乎微不足道。但经过一番思考,我越来越困惑。

根据我的理解ByVal 意味着Sh 只是原始工作表对象的副本,使用ByVal 参数的过程不会导致对原始对象的更改。换句话说,代码所做的应该没有任何影响。

只有当引用被传递给过程时,它们才能修改这些引用所引用的对象。

我错过了什么吗?谢谢

附:我对通过引用/值传递的大部分理解来自其他编程语言,例如 C#。我不知道 VBA 中可能有一些特殊性。

【问题讨论】:

    标签: vba pass-by-reference pass-by-value


    【解决方案1】:

    由于您传递的是对象,因此 ByVal 传递引用的副本(值)。引用的副本(值)仍然指向原始引用所指向的内容。因此,您的方法有效并更改了原始参考指向的内容。

    如果您了解 Java,这在本质上与 Java 相似,可以说一切都是“按值传递”,但是当您将 Object 作为参数传递时,您实际上所做的是传递引用的副本,而不是参考指向的副本。

    【讨论】:

    • 是的。我怎么忘了这个?我不知道 Java,但 C# 本质上具有相同的概念。谢谢。
    • @JohnSmithSr。它实际上在所有语言中都是相同的概念。 ByVal 从不克隆/复制任何对象。
    【解决方案2】:

    在这些情况下,ByVal 会阻止更改原始引用本身的值。

    请看下一篇:

    Module Module1
        Sub Main()
            ' Declare an instance of the class and assign a value to its field.
            Dim c1 As New Class1()
            c1.Field = 5
            Console.WriteLine(c1.Field)
            ' Output: 5
    
            ' ByVal does not prevent changing the value of a field or property.
            ChangeFieldValue(c1)
            Console.WriteLine(c1.Field)
            ' Output: 500
    
            ' ByVal does prevent changing the value of c1 itself. 
            ChangeClassReference(c1)
            Console.WriteLine(c1.Field)
            ' Output: 500
    
            Console.ReadKey()
        End Sub
    
        Public Sub ChangeFieldValue(ByVal cls As Class1)
            cls.Field = 500
        End Sub
    
        Public Sub ChangeClassReference(ByVal cls As Class1)
            cls = New Class1()
            cls.Field = 1000
        End Sub
    
        Public Class Class1
            Public Field As Integer
        End Class
    End Module
    

    【讨论】:

    • 谢谢,爱尤尼也让我想起了这个概念。不错的sn-p。
    • 注意:这是VB.NET代码; OP 正在询问 VBA - 但同样的原则也适用。
    猜你喜欢
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    相关资源
    最近更新 更多