VBA.CBlah 和 CBlah 之间的区别
Difference between VBA.CBlah and CBlah
奇怪的观察:
通常当我想将地址保存到变量中的函数时,我会这样做:
Function getAddress(ByVal func As LongPtr) As LongPtr
getAddress = func
End Function
Sub printAddress()
Dim functionPointer As LongPtr
functionPointer = getAddress(AddressOf myFunc)
Debug.Print functionPointer
End Sub
但是我刚刚发现我可以使用 1-liner
functionPointer = VBA.CLngPtr(AddressOf myFunc)
而
functionPointer = CLngPtr(AddressOf myFunc)
... 不起作用并加注
Compile error:
Expected: expression
这是怎么回事?据我所知,唯一的区别是 CLngPtr
是在全局变量中声明的(class?)而 VBA.CLngPtr
是明确限定的,但我不知道为什么会导致观察到的行为(它们都指向同一个函数,不是吗?)
如果您使用默认的 IDE 设置,关键字和标识符的设置并没有真正不同,这将不是很明显。这是使用不同颜色时的外观:
您可以看到 CLngPtr
像圣诞树一样亮起,看起来与其他关键字一样。将其与 Abs
进行比较,它也是一个函数,但保持浅蓝色,就好像它只是一个标识符一样。
这暗示 CLngPtr
已被 VBA 编译器优化,因此它实际上是内联方法 1,这就是为什么如果您尝试使用 CLngPtr
作为表达式。但是,VBA.CLngPtr
是一个适当的函数,因此可以用作表达式的一部分,但由于未优化路由,性能损失非常小。
你会看到与 say、CLng
或任何转换函数,甚至 Mid
语句(不是函数)相同的事情。 VBA
中有几个函数可能会被编译器内联,通常会因它们是否转换为关键字而有所不同。另请注意,括号的颜色不同。
哎呀,甚至 Debug.Print
也得到了特殊待遇,如果您熟悉它,您可能知道它不完全是 class 也不是模块,但您不能 Print
没有 Debug
.
- 当我们在这里提到 "inlinling" 时,我们是在谈论 VBA 编译器在较低级别的工作,低于我们在源代码级别看到的内容。从源码来看,
C***()
和VBA.C***()
基本是一回事。但是,VBA 编译器可以并且将尝试通过在内部重新安排用于转换的机器指令(或内联函数正在执行的任何操作)来优化这些位。重新排列指令的效果是它可能不再在所有上下文中兼容。在这种情况下,我可以想象(但不知道事实!)CLngPtr()
的内联指令 returns 一个值,而不是一个引用,它与参数声明不兼容,这是为什么当我们尝试将它用作参数时会出现语法错误。请注意,AddressOf
不会发生这种情况——LHS 上的任何其他函数都会有相同的语法错误,因此它与 AddressOf
以及内联方法的所有内容无关。
不是答案,而是更奇怪的思考...
注释中指出编译错误,这有效 (ref):
Sub TestCasting()
Dim value As Variant
Debug.Print "value cast with CBool : " & CBool(value)
Debug.Print "value cast with VBA.CBool : " & VBA.CBool(value)
Debug.Print "value cast with CByte : " & CByte(value)
Debug.Print "value cast with VBA.CByte : " & VBA.CByte(value)
Debug.Print "value cast with CCur : " & CCur(value)
Debug.Print "value cast with VBA.CCur : " & VBA.CCur(value)
Debug.Print "value cast with CDate : " & CDate(value)
Debug.Print "value cast with VBA.CDate : " & VBA.CDate(value)
Debug.Print "value cast with CDbl : " & CDbl(value)
Debug.Print "value cast with VBA.CDbl : " & VBA.CDbl(value)
Debug.Print "value cast with CDec : " & CDec(value)
Debug.Print "value cast with VBA.CDec : " & VBA.CDec(value)
Debug.Print "value cast with CInt : " & CInt(value)
Debug.Print "value cast with VBA.CInt : " & VBA.CInt(value)
Debug.Print "value cast with CLng : " & CLng(value)
Debug.Print "value cast with VBA.CLng : " & VBA.CLng(value)
'--- Compile Error: Sub or Function not found
' (error displayed at run time)
'Debug.Print "value cast with CLngLng: " & CLngLng(value)
'Debug.Print "value cast with VBA.CLngLng: " & VBA.CLngLng(value)
Debug.Print "value cast with CLngPtr: " & CLngPtr(value)
Debug.Print "value cast with VBA.CLngPtr: " & VBA.CLngPtr(value)
Debug.Print "value cast with CSng : " & CSng(value)
Debug.Print "value cast with VBA.CSng : " & VBA.CSng(value)
Debug.Print "value cast with CStr : " & CStr(value)
Debug.Print "value cast with VBA.CStr : " & VBA.CStr(value)
Debug.Print "value cast with CVar : " & CVar(value)
Debug.Print "value cast with VBA.CVar : " & VBA.CVar(value)
End Sub
并添加到上面的代码示例中:
Function myFunc() As String
myFunc = "help!"
End Function
Function getAddress(ByVal func As LongPtr) As LongPtr
getAddress = func
End Function
Sub printAddress()
Dim functionPointer As LongPtr
functionPointer = getAddress(AddressOf myFunc)
Debug.Print functionPointer
functionPointer = VBA.CLngPtr(AddressOf myFunc)
'--- Compile Error: Syntax Error
' (error displayed in red in VBA Editor)
'debug.Print CLngPtr(AddressOf myFunc)
'functionPointer = CLngPtr(AddressOf myFunc)
Debug.Print functionPointer
End Sub
奇怪的观察:
通常当我想将地址保存到变量中的函数时,我会这样做:
Function getAddress(ByVal func As LongPtr) As LongPtr
getAddress = func
End Function
Sub printAddress()
Dim functionPointer As LongPtr
functionPointer = getAddress(AddressOf myFunc)
Debug.Print functionPointer
End Sub
但是我刚刚发现我可以使用 1-liner
functionPointer = VBA.CLngPtr(AddressOf myFunc)
而
functionPointer = CLngPtr(AddressOf myFunc)
... 不起作用并加注
Compile error:
Expected: expression
这是怎么回事?据我所知,唯一的区别是 CLngPtr
是在全局变量中声明的(class?)而 VBA.CLngPtr
是明确限定的,但我不知道为什么会导致观察到的行为(它们都指向同一个函数,不是吗?)
如果您使用默认的 IDE 设置,关键字和标识符的设置并没有真正不同,这将不是很明显。这是使用不同颜色时的外观:
您可以看到 CLngPtr
像圣诞树一样亮起,看起来与其他关键字一样。将其与 Abs
进行比较,它也是一个函数,但保持浅蓝色,就好像它只是一个标识符一样。
这暗示 CLngPtr
已被 VBA 编译器优化,因此它实际上是内联方法 1,这就是为什么如果您尝试使用 CLngPtr
作为表达式。但是,VBA.CLngPtr
是一个适当的函数,因此可以用作表达式的一部分,但由于未优化路由,性能损失非常小。
你会看到与 say、CLng
或任何转换函数,甚至 Mid
语句(不是函数)相同的事情。 VBA
中有几个函数可能会被编译器内联,通常会因它们是否转换为关键字而有所不同。另请注意,括号的颜色不同。
哎呀,甚至 Debug.Print
也得到了特殊待遇,如果您熟悉它,您可能知道它不完全是 class 也不是模块,但您不能 Print
没有 Debug
.
- 当我们在这里提到 "inlinling" 时,我们是在谈论 VBA 编译器在较低级别的工作,低于我们在源代码级别看到的内容。从源码来看,
C***()
和VBA.C***()
基本是一回事。但是,VBA 编译器可以并且将尝试通过在内部重新安排用于转换的机器指令(或内联函数正在执行的任何操作)来优化这些位。重新排列指令的效果是它可能不再在所有上下文中兼容。在这种情况下,我可以想象(但不知道事实!)CLngPtr()
的内联指令 returns 一个值,而不是一个引用,它与参数声明不兼容,这是为什么当我们尝试将它用作参数时会出现语法错误。请注意,AddressOf
不会发生这种情况——LHS 上的任何其他函数都会有相同的语法错误,因此它与AddressOf
以及内联方法的所有内容无关。
不是答案,而是更奇怪的思考...
注释中指出编译错误,这有效 (ref):
Sub TestCasting()
Dim value As Variant
Debug.Print "value cast with CBool : " & CBool(value)
Debug.Print "value cast with VBA.CBool : " & VBA.CBool(value)
Debug.Print "value cast with CByte : " & CByte(value)
Debug.Print "value cast with VBA.CByte : " & VBA.CByte(value)
Debug.Print "value cast with CCur : " & CCur(value)
Debug.Print "value cast with VBA.CCur : " & VBA.CCur(value)
Debug.Print "value cast with CDate : " & CDate(value)
Debug.Print "value cast with VBA.CDate : " & VBA.CDate(value)
Debug.Print "value cast with CDbl : " & CDbl(value)
Debug.Print "value cast with VBA.CDbl : " & VBA.CDbl(value)
Debug.Print "value cast with CDec : " & CDec(value)
Debug.Print "value cast with VBA.CDec : " & VBA.CDec(value)
Debug.Print "value cast with CInt : " & CInt(value)
Debug.Print "value cast with VBA.CInt : " & VBA.CInt(value)
Debug.Print "value cast with CLng : " & CLng(value)
Debug.Print "value cast with VBA.CLng : " & VBA.CLng(value)
'--- Compile Error: Sub or Function not found
' (error displayed at run time)
'Debug.Print "value cast with CLngLng: " & CLngLng(value)
'Debug.Print "value cast with VBA.CLngLng: " & VBA.CLngLng(value)
Debug.Print "value cast with CLngPtr: " & CLngPtr(value)
Debug.Print "value cast with VBA.CLngPtr: " & VBA.CLngPtr(value)
Debug.Print "value cast with CSng : " & CSng(value)
Debug.Print "value cast with VBA.CSng : " & VBA.CSng(value)
Debug.Print "value cast with CStr : " & CStr(value)
Debug.Print "value cast with VBA.CStr : " & VBA.CStr(value)
Debug.Print "value cast with CVar : " & CVar(value)
Debug.Print "value cast with VBA.CVar : " & VBA.CVar(value)
End Sub
并添加到上面的代码示例中:
Function myFunc() As String
myFunc = "help!"
End Function
Function getAddress(ByVal func As LongPtr) As LongPtr
getAddress = func
End Function
Sub printAddress()
Dim functionPointer As LongPtr
functionPointer = getAddress(AddressOf myFunc)
Debug.Print functionPointer
functionPointer = VBA.CLngPtr(AddressOf myFunc)
'--- Compile Error: Syntax Error
' (error displayed in red in VBA Editor)
'debug.Print CLngPtr(AddressOf myFunc)
'functionPointer = CLngPtr(AddressOf myFunc)
Debug.Print functionPointer
End Sub