简体   繁体   English

数组“下标超出范围”的异常行为

[英]Array “subscript out of range” odd behavior

Consider this code in MS Word VBA: 在MS Word VBA中考虑以下代码:

Sub Test()
    Dim x() As Document
    ReDim Preserve x(UBound(x) + 1)
    Set x(UBound(x)) = Application.ActiveDocument
End Sub

If I place the cursor inside and hit F5 to run it, I get an error 如果我将光标放在里面并按F5键运行它,则会收到错误消息

subscript out of range 下标超出范围

on ReDim Preserve x(UBound(x) + 1) . ReDim Preserve x(UBound(x) + 1) Specifically, it doesn't like UBound(x) , although it should return -1 based on MSDN (see under "return value"). 具体来说,它不喜欢UBound(x) ,尽管它应该基于MSDN返回-1 (请参见“返回值”下的内容)。

Now, if I set a break point on ReDim Preserve x(UBound(x) + 1) , run it, and then hover the cursor over UBound(x) , it indicates the same thing: 现在,如果我在ReDim Preserve x(UBound(x) + 1)上设置一个断点,运行它,然后将光标悬停在UBound(x) ,则表明相同:

在此处输入图片说明

But I've discovered that if I then hover over the variable x in the following line: 但是我发现,如果我将鼠标悬停在以下行中的变量x上:

在此处输入图片说明

and then go back and again hover over UBound(x) in the line above, I get a different result: 然后返回并再次将鼠标悬停在上一行的UBound(x)上,我得到一个不同的结果:

在此处输入图片说明

Then, if I hit F5 to run the rest of the code, indeed, I get no error that time. 然后,如果我按F5键运行其余代码,的确,那时候我没有出错。

Furthermore, if I change my code to add IsArray(x) : 此外,如果我更改代码以添加IsArray(x)

Sub Test()
    Dim x() As Document
    IsArray (x) 'This is just here to preclude VBA array "bug"
    ReDim Preserve x(UBound(x) + 1)
    Set x(UBound(x)) = Application.ActiveDocument
End Sub

It also runs fine. 它也运行良好。 What is going on, and how can I get my code to work at runtime without the IsArray(x) hack? 发生了什么,如何在没有IsArray(x) hack的情况下使代码在运行时工作?

MSDN: MSDN:

If Array has only one element, UBound returns 0. If Array has no elements, for example if it is a zero-length string, UBound returns -1. 如果Array只有一个元素,则UBound返回0。如果Array没有元素,例如,如果它是长度为零的字符串,则UBound返回-1。

It isn't that the array has no elements, it is un-initialized, or doesn't have dimensions. 这并不是说数组没有元素,未初始化或没有维度。 You shouldn't rely on the value of UBound without first using ReDim on the array at least once, or without the use of error handling. 在不首先在数组上至少使用一次ReDim或不使用错误处理的情况下,您不应该依赖UBound的值。

A better approach is to use error handling: 更好的方法是使用错误处理:

Dim x() As Document

Dim n As Long
On Error Resume Next
Err.Clear
n = LBound(x)
If Err.Number = 0 Then
    Debug.Print "Array is allocated."
Else
    Debug.Print "Array is not allocated."
End If

See this link for other considerations. 其他注意事项,请参见此链接

Alternatively, if possible, ensure that the array is dimensioned ( ReDim ) as least once. 或者,如果可能,请确保数组的尺寸至少为一次( ReDim )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM