向Currency类型属性传字符串未报错,如何禁用自动转换?
关于VBA中Currency参数自动转换的问题解答
为什么字符串传递给Currency参数不会报错?
这是VBA(包括VB6)的默认行为——它会自动执行隐式类型转换。当你传入的参数类型和目标参数类型不匹配时,只要VBA能够安全地将前者转换为后者(比如你的示例中"10"是合法的数值字符串,可以无歧义转为Currency类型),它就会在后台自动完成转换,不会抛出错误。
但如果传入的是无法转换的字符串(比如"abc"),VBA就会触发"类型不匹配"的错误了。
如何阻止这种自动转换?
VBA并没有像VB.NET里的Option Strict On那样的编译选项来直接禁用隐式转换,不过我们可以通过手动在属性内部添加类型校验的方式来实现:
推荐方案:将参数改为Variant并校验原始类型
把Property Let的参数类型改为Variant,这样我们就能获取到用户传入的原始值类型,然后在属性内部检查,如果不是Currency类型就抛出错误。修改后的Model类代码如下:
Option Explicit Private m_cash As Currency Public Property Let Cash(ByVal newCash As Variant) ' 检查传入值的类型是否为Currency If VarType(newCash) <> vbCurrency Then ' 抛出自定义错误,提示只能传入Currency类型 Err.Raise vbObjectError + 1001, , "参数必须为Currency类型,不允许自动转换" End If m_cash = newCash End Property
测试验证
修改后,当你在Test过程中传入字符串时,就会直接触发错误:
Option Explicit Public Sub Test() Dim modelObj As Model Dim testString As String Set modelObj = New Model testString = "10" ' 这行代码现在会抛出错误,阻止了自动转换 modelObj.Cash = testString ' 正确的调用方式(明确传入Currency类型) modelObj.Cash = CCur(testString) ' 或者直接写 10@(@是Currency类型的字面量后缀) End Sub
为什么不能直接用Currency参数校验?
如果我们保持参数为Currency类型,那么在进入Property Let之前,VBA已经完成了隐式转换,此时参数已经是Currency类型,我们无法再检测到用户传入的原始类型,也就无法阻止转换行为。所以必须用Variant来接收原始值,才能实现严格的类型校验。
内容的提问来源于stack exchange,提问作者Artur Fityka
相关产品推荐
相关产品推荐

