请教VB高手preserve的用法?

在定义动态数组时,为什么说是用preseve只能改变最后一维的大小,前面几位大小不能改变呢?那么为什么说在Redim语句后加preseve可以保留原来数组的大小呢?

ReDim 语句用来定义或重定义原来已经用带空圆括号(没有维数下标)的 Private、Public 或 Dim 语句声明过的动态数组的大小。

可以使用 ReDim 语句反复地改变数组的元素以及维数的数目,但是不能在将一个数组定义为某种数据类型之后,再使用 ReDim 将该数组改为其它数据类型,除非是 Variant 所包含的数组。如果该数组确实是包含在某个 Variant 中,且没有使用 Preserve 关键字,则可以使用 As type 子句来改变其元素的类型,但在使用了此关键字的情况下,是不允许改变任何数据类型的。

如果使用了 Preserve 关键字,就只能重定义数组最末维的大小,且根本不能改变维数的数目。例如,如果数组就是一维的,则可以重定义该维的大小,因为它是最末维,也是仅有的一维。不过,如果数组是二维或更多维时,则只有改变其最末维才能同时仍保留数组中的内容。下面的示例介绍了如何在为已有的动态数组增加其最末维大小的同时而不清除其中所含的任何数据。

ReDim X(10, 10, 10)
. . .
ReDim Preserve X(10, 10, 15)

同样地,在使用 Preserve 时,只能通过改变上界来改变数组的大小;改变下界则会导致错误。

如果将数组改小,则被删除的元素中的数据就会丢失。如果按地址将数组传递给某个过程,那么不要在该过程内重定义该数组的各维的大小。

在初始化变量时,数值变量被初始化为 0,变长的字符串被初始化为一个零长度的字符串 (""),而定长的字符串则用 0 填充。Variant 变量被初始化为 Empty。用户自定义类型的变量的每个元素作为各自独立的变量进行初始化。在使用引用对象的变量之前,必须使用 Set 语句将一个已有的对象赋给该变量。在被赋值之前,所声明的对象变量有一个特定值 Nothing,这个值表示该变量没有指向任何对象的实例。

小心 如果 ReDim 语句所使用的变量在模块级别或过程级别不存在,则该语句就相当于一个声明语句。如果此后在一个更广的范围内又创建了同名的变量,即使使用了 Option Explicit,ReDim 也将使用后声明的这个变量,且不会导致编译错误。为了避免这种冲突,就不应把 ReDim 作为声明语句使用,而只应作为重定义数组大小的语句。

注意 要改变 Variant 所包含的数组的大小,必须在试图改变其数组大小之前显式声明该 Variant 变量。

保留动态数组的内容
每次执行 ReDim 语句时,当前存储在数组中的值都会全部丢失。Visual Basi 重新将数组元素的值置为 Empty(对 Variant 数组)、置为 0(对 Numeric 数组)、置为 零长度字符串(对 String 数组)或者置为 Nothing(对于对象的数组)。

在为新数据准备数组,或者要缩减数组大小以节省内存时,这样做是非常有用的。有时希望改变数组大小又不丢失数组中的数据。使用具有 Preserve 关键字的 ReDim 语句就可做到这点。例如,使用 UBound 函数引用上界,使数组扩大、增加一个元素,而现有元素的值并未丢失:

ReDim Preserve DynArray (UBound (DynArray) + 1)

在用 Preserve 关键字时,只能改变多维数组中最后一维的上界;如果改变了其它维或最后一维的下界,那么运行时就会出错。所以可这样编程:

ReDim Preserve Matrix (10, UBound (Matrix, 2) + 1)

而不可这样编程:

ReDim Preserve Matrix (UBound (Matrix, 1) + 1, 10)
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-06-22
ReDim 语句用来定义或重定义原来已经用带空圆括号(没有维数下标)的 Private、Public 或 Dim 语句声明过的动态数组的大小。

可以使用 ReDim 语句反复地改变数组的元素以及维数的数目,但是不能在将一个数组定义为某种数据类型之后,再使用 ReDim 将该数组改为其它数据类型,除非是 Variant 所包含的数组。如果该数组确实是包含在某个 Variant 中,且没有使用 Preserve 关键字,则可以使用 As type 子句来改变其元素的类型,但在使用了此关键字的情况下,是不允许改变任何数据类型的。

如果使用了 Preserve 关键字,就只能重定义数组最末维的大小,且根本不能改变维数的数目。例如,如果数组就是一维的,则可以重定义该维的大小,因为它是最末维,也是仅有的一维。不过,如果数组是二维或更多维时,则只有改变其最末维才能同时仍保留数组中的内容。下面的示例介绍了如何在为已有的动态数组增加其最末维大小的同时而不清除其中所含的任何数据。

ReDim X(10, 10, 10)
. . .
ReDim Preserve X(10, 10, 15)

同样地,在使用 Preserve 时,只能通过改变上界来改变数组的大小;改变下界则会导致错误。

如果将数组改小,则被删除的元素中的数据就会丢失。如果按地址将数组传递给某个过程,那么不要在该过程内重定义该数组的各维的大小。

在初始化变量时,数值变量被初始化为 0,变长的字符串被初始化为一个零长度的字符串 (""),而定长的字符串则用 0 填充。Variant 变量被初始化为 Empty。用户自定义类型的变量的每个元素作为各自独立的变量进行初始化。在使用引用对象的变量之前,必须使用 Set 语句将一个已有的对象赋给该变量。在被赋值之前,所声明的对象变量有一个特定值 Nothing,这个值表示该变量没有指向任何对象的实例。

小心 如果 ReDim 语句所使用的变量在模块级别或过程级别不存在,则该语句就相当于一个声明语句。如果此后在一个更广的范围内又创建了同名的变量,即使使用了 Option Explicit,ReDim 也将使用后声明的这个变量,且不会导致编译错误。为了避免这种冲突,就不应把 ReDim 作为声明语句使用,而只应作为重定义数组大小的语句。

注意 要改变 Variant 所包含的数组的大小,必须在试图改变其数组大小之前显式声明该 Variant 变量。

保留动态数组的内容
每次执行 ReDim 语句时,当前存储在数组中的值都会全部丢失。Visual Basi 重新将数组元素的值置为 Empty(对 Variant 数组)、置为 0(对 Numeric 数组)、置为 零长度字符串(对 String 数组)或者置为 Nothing(对于对象的数组)。

在为新数据准备数组,或者要缩减数组大小以节省内存时,这样做是非常有用的。有时希望改变数组大小又不丢失数组中的数据。使用具有 Preserve 关键字的 ReDim 语句就可做到这点。例如,使用 UBound 函数引用上界,使数组扩大、增加一个元素,而现有元素的值并未丢失:

ReDim Preserve DynArray (UBound (DynArray) + 1)

在用 Preserve 关键字时,只能改变多维数组中最后一维的上界;如果改变了其它维或最后一维的下界,那么运行时就会出错。所以可这样编程:

ReDim Preserve Matrix (10, UBound (Matrix, 2) + 1)

而不可这样编程:
第2个回答  2014-08-06
摘自微软的msdn:
Visual Basic
Visual Basic 语言参考

ReDim 语句 (Visual Basic)
更新:2007 年 11 月
为数组变量重新分配存储空间。

ReDim [ Preserve ] name(boundlist) [ , name(boundlist) [, ... ] ]

各部分说明
Preserve
可选项。修饰符,当仅更改最后一个维度的大小时,用来保留现有数组中的数据。
name
必选。数组变量的名称。请参见已声明元素的名称。
boundlist
必选。列出重新定义的数组各个维度的界限。
备注
可以使用ReDim语句来更改某个已声明数组的一个或多个维度的大小。如果有一个较大的数组,并且您不再需要它的某些元素,ReDim可通过减小数组大小来释放内存。另一方面,如果代码确定某个数组需要更多元素,ReDim也可以添加它们。
ReDim语句仅适用于数组。它在标量(只包含单一值的变量)、集合或结构上是无效的。请注意,如果将变量声明为采用Array类型,ReDim语句将没有足够的类型信息来创建新数组。
仅可以在过程级使用ReDim。这意味着,变量的“声明上下文”必须是过程,而不能是源文件、命名空间、接口、类、结构、模块或块。有关更多信息,请参见声明上下文和默认访问级别。
规则
· 修饰符。只能指定Preserve修饰符,并且,如果这样做,就不能省略ReDim关键字。
· 多个变量。可以在同一声明语句中调整多个数组变量的大小,同时为每个变量指定name和boundlist部分。以逗号分隔多个变量。
· 数组界限。boundlist中的各个条目可指定该维度的下限和上限。不管是否指定,下限总是为零。上限是该上标的最大可能值,而不是维度的长度(即上限加 1)。每个上标都可能在零到其上限值之间变动。
boundlist中维度的数量必须与数组的原始秩匹配。
· 空数组。可以使用 -1 来声明数组维度的上限。这表示数组为空,但不是Nothing (Visual Basic)。有关更多信息,请参见如何:创建不含任何元素的数组。然而,Visual Basic 代码不能成功访问此类数组。如果试图这样做,则在执行期间会发生 IndexOutOfRangeException 错误。
· 数据类型。ReDim语句无法更改数组变量或其元素的数据类型。
· 初始化。ReDim语句无法为数组元素提供新的初始化值。
· 秩。ReDim语句无法更改数组的秩(维数)。
· 使用 Preserve 调整大小。如果使用Preserve,则只能调整数组最后一个维度的大小,对于其他每个维度,您必须指定它在现有数组中已经具有的相同界限。
例如,如果数组只有一维,而可以调整该维度的大小并依然保留数组的所有内容,因为您更改的是最后一个并且唯一的维度。然而,如果数组具有两个或多个维度,则如果使用Preserve将仅可以更改最后维度的大小。
· 属性。可以在容纳值数组的属性上使用ReDim。
行为
· 数组替换。ReDim释放现有数组并且创建具有相同秩的新数组。新数组将替换数组变量中已释放的数组。
· 不使用 Preserve 初始化。如果未指定Preserve,ReDim会将新数组的元素初始化为它们数据类型的默认值。
· 使用 Preserve 初始化。如果指定Preserve修饰符,Visual Basic 会将这些元素从现有数组复制到新数组。
示例
下面的示例将增加某个动态数组最后一个维度的大小(不会丢失数组中的任何现有数据),然后减小该大小(会有部分数据丢失)。最后,它会将大小重新减小到其原始值,并重新初始化所有数组元素。

Visual Basic

Dim intArray(10, 10, 10) AsInteger

ReDim Preserve intArray(10, 10, 20)

ReDim Preserve intArray(10, 10, 15)

ReDim intArray(10, 10, 10)

第一个ReDim将创建一个新数组,该数组将替换变量intArray中的现有数组。ReDim会将所有元素从现有数组复制到新数组。它还会在每一层中每个行的结尾另外添加 10 列,并将这些新列中的元素初始化为 0(数组元素类型Integer的默认值)。
第二个ReDim创建另一个新数组,复制所有适合的元素。然而,每一层的每一行的结尾丢失了 5 列。如果不再使用这些栏,丢失将不成问题。减小大型数组的大小能够释放不再需要的内存。
第三个ReDim仍然创建另一个新数组,同时从每一层中每个行的结尾移除另外 5 列。这一次它不会复制任何现有元素。这样即会将数组恢复为其原始大小,并将它的所有元素还原为它们的原始默认值。

请参见
任务
如何:创建不含任何元素的数组
概念
ReDim 语句(针对 Visual Basic 6.0 用户)
数组大小声明(针对 Visual Basic 6.0 用户)
参考
Const 语句 (Visual Basic)
Dim 语句 (Visual Basic)
Erase 语句 (Visual Basic)
Nothing (Visual Basic)
IndexOutOfRangeException
相似回答