VB-101:传递数组ByVal vs ByRef [英] VB-101: Passing Arrays ByVal vs ByRef

查看:95
本文介绍了VB-101:传递数组ByVal vs ByRef的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在附带的示例中,我明白引用不会更改

如果Val传递数组。我不明白的是行结果

99(如果可以通过行号找到这个),这是子程序后面的

的最后一行:


''程序修改数组元素并分配

''新引用(注意ByVal)

Sub FirstDouble(ByVal数组为整数())

Dim i As Integer


''每个元素值加倍

For i = 0 to array.GetUpperBound( 0)

数组(i)* = 2

下一页


''创建新引用并将其分配给数组

array = New Integer(){11,12,13}

End Sub''FirstDouble


由于行所在的值数组''数组''由

值填充11,12和13是同一子程序的后半部分

之前的值变化在同一个阵列中,我希望这些

值作为输出打印到屏幕上。对我来说,看起来像返回到调用函数的数组

值首先加倍,而

只是被覆盖了。显然这不会发生。


有人可以解释为什么会这样吗?

(完整的例子附在下面


感谢您的帮助,


John


****************** ***************


模块modArrayReferenceTest


Sub Main()

Dim i As Integer


''声明数组引用

Dim firstArray As Integer()

Dim firstArrayCopy As Integer ()


''分配firstArray并复制其引用

firstArray = New Integer(){1,2,3}

firstArrayCopy = firstArray

Console.WriteLine(使用ByVal测试传递数组引用& _

。)

Console.Write(" firstArray before"& _

" call FirstDouble:")


''打印firstArray的内容

For i = 0 to firstArray.GetUpperBound(0)

Console.Write(firstArray(i)& " ")

下一页


''使用ByVal传递firstArray

FirstDouble(firstArray)


Console.Write(vbCrLf&" firstArray的内容"& _

" call FirstDouble:")


''打印firstArray的内容

For i = 0 to firstArray.GetUpperBound(0)

Console.Write(firstArray(i)&"")

下一页


''测试FirstDouble是否更改了引用

如果firstArray是firstArrayCopy那么

控制台.WriteLine(vbCrLf&"引用是& _

"等等。)

Else

控制台。 WriteLine(vbCrLf&" the references are"& _

" not equal。")

结束如果


''声明数组引用

Dim secondArray As Integer()

Dim secondArrayCopy As Integer()


''分配secondArra y并复制其参考资料

secondArray = New Integer(){1,2,3}

secondArrayCopy = secondArray


控制台.WriteLine(vbCrLf& 测试传递阵列 &安培; _

使用ByRef引用。

Console.Write(" secondArray before"& _

" ;调用SecondDouble:")


''在程序调用之前打印secondArray的内容

For i = 0 to secondArray.GetUpperBound(0)

Console.Write(secondArray(i)&"")

Next


''使用ByRef传递secondArray
SecondDouble(secondArray)

Console.Write(vbCrLf&" secondArray的内容& _

") SecondDouble:")


''在程序调用后打印secondArray的内容

For i = 0 to secondArray.GetUpperBound(0)

Console.Write(secondArray(i)&"")

Next


''测试引用是否被SecondDouble改变

如果secondArray是secondArrayCopy那么

Console.WriteLine(vbCrLf&" Th参考文献是 &安培; _

等于。

否则

Console.WriteLine(vbCrLf&"引用是"& _

不等于。

结束如果


End Sub''Main

''程序修改数组元素并指定

''新引用(注意ByVal)

Sub FirstDouble(ByVal数组为整数())

Dim i As Integer


''每个元素值加倍

For i = 0 to array.GetUpperBound(0)

数组(i)* = 2

下一页


''创建新参考并将其分配给数组

array = New Integer(){11,12,13}

End Sub''FirstDouble


''程序修改数组元素并指定

''新参考(注释ByRef)

Sub SecondDouble(ByRef数组为整数())

Dim i As Integer


''数组的双重内容

For i = 0 to array.GetUp perBound(0)

数组(i)* = 2

下一页


''创建新引用并将其分配给数组

array = New Integer(){11,12,13}

End Sub''SecondDouble


结束模块'' modPassArray


************************************* ****

解决方案




数组是按字节传递的。你在

子程序中对数组所做的任何操作都不会被发回。如果你想能够对阵列进行任何改变
,请将其传递给它。




---- ----------------

" John Pass" <乔****** @ discussions.microsoft.com>在消息中写道

新闻:F6 ********************************** @ microsof t.com ...



在附带的例子中,我明白引用没有改变

如果数组是通过Val。我不明白的是行结果

99(如果可以通过行号找到这个),这是子程序后面的

的最后一行:


''程序修改数组元素并分配

''新引用(注意ByVal)

Sub FirstDouble(ByVal数组为整数())

Dim i As Integer


''每个元素值加倍

For i = 0 to array.GetUpperBound( 0)

数组(i)* = 2

下一页


''创建新引用并将其分配给数组

array = New Integer(){11,12,13}

End Sub''FirstDouble


由于行所在的值数组''数组''由

值填充11,12和13是同一子程序的后半部分

之前的值变化在同一个阵列中,我希望这些

值作为输出打印到屏幕上。对我来说,看起来像返回到调用函数的数组

值首先加倍,而

只是被覆盖了。显然这不会发生。


有人可以解释为什么会这样吗?

(完整的例子附在下面


感谢您的帮助,


John


****************** ***************


模块modArrayReferenceTest


Sub Main()

Dim i As Integer


''声明数组引用

Dim firstArray As Integer()

Dim firstArrayCopy As Integer ()


''分配firstArray并复制其引用

firstArray = New Integer(){1,2,3}

firstArrayCopy = firstArray

Console.WriteLine(使用ByVal测试传递数组引用& _

。)

Console.Write(" firstArray before"& _

" call FirstDouble:")


''打印firstArray的内容

For i = 0 to firstArray.GetUpperBound(0)

Console.Write(firstArray(i)& " ")

下一页


''使用ByVal传递firstArray

FirstDouble(firstArray)


Console.Write(vbCrLf&" firstArray的内容"& _

" call FirstDouble:")


''打印firstArray的内容

For i = 0 to firstArray.GetUpperBound(0)

Console.Write(firstArray(i)&"")

下一页


''测试FirstDouble是否更改了引用

如果firstArray是firstArrayCopy那么

控制台.WriteLine(vbCrLf&"引用是& _

"等等。)

Else

控制台。 WriteLine(vbCrLf&" the references are"& _

" not equal。")

结束如果


''声明数组引用

Dim secondArray As Integer()

Dim secondArrayCopy As Integer()


''分配secondArra y并复制其参考资料

secondArray = New Integer(){1,2,3}

secondArrayCopy = secondArray


控制台.WriteLine(vbCrLf& 测试传递阵列 &安培; _

使用ByRef引用。

Console.Write(" secondArray before"& _

" ;调用SecondDouble:")


''在程序调用之前打印secondArray的内容

For i = 0 to secondArray.GetUpperBound(0)

Console.Write(secondArray(i)&"")

Next


''使用ByRef传递secondArray
SecondDouble(secondArray)

Console.Write(vbCrLf&" secondArray的内容& _

") SecondDouble:")


''在程序调用后打印secondArray的内容

For i = 0 to secondArray.GetUpperBound(0)

Console.Write(secondArray(i)&"")

Next


''测试引用是否被SecondDouble改变

如果secondArray是secondArrayCopy那么

Console.WriteLine(vbCrLf&" Th参考文献是 &安培; _

等于。

否则

Console.WriteLine(vbCrLf&"引用是"& _

不等于。

结束如果


End Sub''Main

''程序修改数组元素并指定

''新引用(注意ByVal)

Sub FirstDouble(ByVal数组为整数())

Dim i As Integer


''每个元素值加倍

For i = 0 to array.GetUpperBound(0)

数组(i)* = 2

下一页


''创建新参考并将其分配给数组

array = New Integer(){11,12,13}

End Sub''FirstDouble


''程序修改数组元素并指定

''新参考(注释ByRef)

Sub SecondDouble(ByRef数组为整数())

Dim i As Integer


''数组的双重内容

For i = 0 to array.GetUp perBound(0)

数组(i)* = 2

下一页


''创建新引用并将其分配给数组

array = New Integer(){11,12,13}

End Sub''SecondDouble


结束模块'' modPassArray


************************************* ****





" John Pass" <乔****** @ discussions.microsoft.com>在消息中写道

新闻:F6 ********************************** @ microsof t.com ...





:在附带的例子中,我明白引用不是

:如果Val传递数组,则更改。我不明白的是

:第99行的结果(如果可以通过行号找到),这是

:以下子例程的最后一行:



:''程序修改数组的元素并分配

:''新参考(注意ByVal)

:Sub FirstDouble(ByVal数组为整数())

:Dim i As Integer



:''每个元素值加倍

:for i = 0 to array.GetUpperBound(0)

:array(i)* = 2

:Next



:''创建新引用并将其分配给数组

:array = New Integer(){11,12,13}

:End Sub''FirstDouble



:由于数组''array''的值被
填充的行
:值11,12和13是同一子程序的后半部分

:同一个值的早期值变化发生了,我会

:期望这些值作为输出打印到屏幕上。对我来说,它是
:看起来像返回到调用函数的数组值

:第一次加倍并且只是被覆盖了。显然这是

:没有发生。



:谁能解释为什么会这样?

:(完整的例子如下:



:感谢您的帮助,



:John

我要在前面说明我不完全确定我对这个问题的理解是否正确(尽管''我相信它或者我不会' 't

提供这个帖子),所以暂时取这个。

当你将参考类型作为参数传递给函数调用时,你



堆上传递对该对象的内存位置的引用。函数中参数''array''中传递的值

firstDouble和secondDouble是引用到堆上的数组实例的一个实例。因此,这些函数可以修改数组中的数据,因为它们有一个指向它的内存指针。 br />
在每个函数调用中,都有一个新的集成er数组被实例化并分配给变量''array''
。这些数组也在堆上,任何具有对这些对象的引用的
方法都可以修改它们。

如你所知,这两个函数之间的关键区别是

firstDouble接受数组参数''ByVal''而secondDouble

接受数组''ByRef''。那个(因为我也确定你知道)是

关键到不同的行为。

当每个函数创建一个新的数组对象时,对它的引用是

然后分配给变量数组。但是,由于参数数组是传递给函数firstDouble''ByVal'的
,当函数返回并且变量firstArray仍然被丢弃时,新的参考值是



引用堆上的原始数组对象。然而,当secondDouble

返回时,对新整数数组的引用被分配给

变量firstArray。

我不确定是否这是更清楚的,所以让我尝试另一种方法。

当你在代码中达到这一点时:


firstArray = New Integer(){1, 2,2}

firstArrayCopy = firstArray

在堆上创建一个数组对象,其中包含两个引用:''firstArray''

和' firstArrayCopy。这两个引用只是指向数组对象驻留在堆上的相同内存位置的指针。

当最初调用函数''firstDouble''时,* copy *引用

''firstArray''被传递给堆栈上的函数(对象本身

没有添加到堆栈中,但引用它的参数是) 。现在

有* 3 *引用单个对象:''firstArray'',

''firstArrayCopy''(本地到子''Main'')和''array''(本地功能

''firstDouble'')。由于函数''firstDouble''引用了对象的内存位置,因此它可以完全访问它并且可以修改

它。

在函数''firstDouble''退出之前,第二个数组对象是在堆上创建的
,并且对该对象的引用被分配给

变量' '阵列。现在我们有两个独立的数组对象和三个

引用。引用''firstArray''和''firstArrayCopy''仍然指向

第一个数组对象和引用''array''指向第二个。

尽快函数''firstDouble''退出,对第二个数组

对象的引用在堆栈上。但是,由于它是在''ByVal''中传递的,所以它被丢弃了,而且没有进一步使用。现在我们仍然有两个数组对象和

两个引用。但是,引用''firstArray''和'firstArrayCopy''

仍然指向同一个数组对象和第二个对象(在

函数''firstDouble''中创建)不再被引用,并且可能是垃圾收集过程回收的


为了讨论,让'忽略第一个数组对象

堆并且假装此时没有任何东西。

当你在代码中达到* this *点时:


secondArray = New Integer(){1,2,3}

secondArrayCopy = secondArray

a在堆上创建新的数组对象,同样有两个引用:

''secondArray''和''secondArrayCopy''。

再次,当函数''secondDouble''最初被调用时,
$ b的副本$ b reference''secondArray''传递给堆栈上的函数创建

3对该单个对象的引用:'' secondArray'',''secondArrayCopy''

和''array''。

就在函数''secondDouble''退出之前,另一个数组对象是

在堆上创建,对该对象的引用被分配给

变量''array''。一旦函数''secondDouble''退出,对第二个数组对象的

引用就在堆栈上。

*这个*时间,但是,引用被传递了在''ByRef'中,所以对新数组对象的

引用从堆栈中复制并导致

变量''secondArray''指向该对象而不是第一个

对象。这就是为什么当函数''secondDouble''退出时,''secondArray''

和''secondArrayCopy''不再相等 - 他们指向两个

不同的物品!

拉尔夫



:******************** *************



:模块modArrayReferenceTest



:Sub Main()

:Dim i As Integer



:''声明数组引用

: Dim firstArray As Integer()

:Dim firstArrayCopy As Integer()



:''分配firstArray并复制其引用

:firstArray = New Integer(){1,2,3}

:firstArrayCopy = firstArray



:控制台.WriteLine(测试传递数组引用& _

:使用ByVal。)

:Console.Write(" firstArray之前的内容) & _

:调用FirstDouble:)



:''打印firstArray的内容

:对于i = 0 To firstArray.GetUpperBound(0)

:Console.Write(firstArray(i)& " )
:下一页



:''使用ByVal传递firstArray

:FirstDouble(firstArray)



:Console.Write(vbCrLf&" firstArray的内容"& _

:"调用FirstDouble: ")



:''打印firstArray的内容

:对于i = 0到firstArray.GetUpperBound(0)

:Console.Write(firstArray(i)&"")

:下一页



:' '测试引用是否被FirstDouble更改

:如果firstArray是firstArrayCopy那么

:Console.WriteLine(vbCrLf&"引用是& _

:等于。

:否则

:Console.WriteLine(vbCrLf&"引用是"& _

:不等于。

:E nd如果



:''声明数组引用

:Dim secondArray As Integer()

:Dim secondArrayCopy As Integer()



:''分配secondArray并复制其引用

:secondArray = New Integer(){1,2 ,3 $

:secondArrayCopy = secondArray



:Console.WriteLine(vbCrLf& 测试传递阵列 &安培; _

:使用ByRef引用。

:Console.Write(" secondArray之前的内容"& _

:调用SecondDouble:)



:''在程序调用之前打印secondArray的内容

:对于i = 0 to secondArray.GetUpperBound(0)

:Console.Write(secondArray(i)&"")

:Next



:''使用ByRef传递secondArray

:SecondDouble(secondArray)



:Console.Write( vbCrLf&SecondArray的内容& _

:在调用SecondDouble之后:)



:' '程序调用后打印secondArray的内容

:对于i = 0到secondArray.GetUpperBound(0)

:Console.Write(secondArray(i)&"" ;)

:下一页



:''测试引用是否被SecondDouble更改

:如果secondArray是secondArrayCopy那么

:Console.WriteLine(vbCrLf& 参考文献是 &安培; _

:等于。

:否则

:Console.WriteLine(vbCrLf&" the references are & _

:不等于。

:结束如果



:结束Sub''Main



:''程序修改数组的元素并分配

:''新参考(注意ByVal)

:Sub FirstDouble(ByVal数组为整数())

:Dim i As Integer



:''每个元素值加倍

:对于i = 0到array.GetUpperBound(0)

:array(i)* = 2

:下一个



:''创建新引用并将其分配给数组

:array = New Integer(){11,12,13}

:结束Sub''FirstDouble



:''程序修改数组元素并分配

: ''新参考(注释ByRef)

:Sub SecondDouble(ByRef数组为整数())

:Dim i As Integer



:''数组的双重内容

:对于i = 0到array.GetUpperBound(0)

:array(i)* = 2

:下一页



:''创建新引用并将其分配给数组

:array = New Integer(){11 ,12,13}

:结束Sub''SecondDouble



:结束模块''modPassArray



:**************************************** *


" John Pass" <乔****** @ discussions.microsoft.com> schrieb:

''程序修改数组元素并指定
''新引用(注意ByVal)
Sub FirstDouble(ByVal数组为整数())
Dim我作为整数

''每个元素值加倍
对于i = 0到array.GetUpperBound(0)
array(i)* = 2
下一个

''创建新引用并将其分配给数组
array = New Integer(){11,12,13}
End Sub''FirstDouble

由于数组''数组''的值由
值11,12和13填充的行是同一子程序的后半部分,其中
早期更改了值发生相同的数组,我希望将这些值作为输出打印到屏幕上。对我来说,看起来返回到调用函数的
数组值首先加倍并且只是覆盖了。显然这不会发生。




数组是引用类型,而整数则不是。因此,一个

整数数组是一个引用类型。通过使用

''ByVal'将数组传递给方法,将复制指向数组的指针,并将副本传递给

方法。因此,您可以更改数组的元素,但不能更改

整个数组。换句话说,为参数指定一个新的数组对象

不会改变传递给方法的变量的引用。

你将不得不传递数组''ByRef''以便能够做到这一点。


-

MS Herfried K. Wagner

MVP< URL:http://dotnet.mvps.org/>

VB< URL:http://classicvb.org/petition/>


Hi,
In the attached example, I do understand that the references are not changed
if an array is passed by Val. What I do not understand is the result of line
99 (If one can find this by line number) which is the last line of the
following sub routine:

'' procedure modifies elements of array and assigns
'' new reference (note ByVal)
Sub FirstDouble(ByVal array As Integer())
Dim i As Integer

'' double each element value
For i = 0 To array.GetUpperBound(0)
array(i) *= 2
Next

'' create new reference and assign it to array
array = New Integer() {11, 12, 13}
End Sub '' FirstDouble

Since the line where the values of the array ''array'' are filled by the
values 11, 12 and 13 is the later part of the same sub-routine where the
earlier changes of values in the same array took place, I would expect these
values to be printed to the screen as output. To me, it looks like the array
values being returned to the calling function were first doubled and that
simply overwritten. Apparently this does not happen.

Can anyone explain why this happens?
(The complete example is attached below

Thanks for your help,

John

*********************************

Module modArrayReferenceTest

Sub Main()
Dim i As Integer

'' declare array references
Dim firstArray As Integer()
Dim firstArrayCopy As Integer()

'' allocate firstArray and copy its reference
firstArray = New Integer() {1, 2, 3}
firstArrayCopy = firstArray

Console.WriteLine("Test passing array reference " & _
"using ByVal.")
Console.Write("Contents of firstArray before " & _
"calling FirstDouble: ")

'' print contents of firstArray
For i = 0 To firstArray.GetUpperBound(0)
Console.Write(firstArray(i) & " ")
Next

'' pass firstArray using ByVal
FirstDouble(firstArray)

Console.Write(vbCrLf & "Contents of firstArray after " & _
"calling FirstDouble: ")

'' print contents of firstArray
For i = 0 To firstArray.GetUpperBound(0)
Console.Write(firstArray(i) & " ")
Next

'' test whether reference was changed by FirstDouble
If firstArray Is firstArrayCopy Then
Console.WriteLine(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLine(vbCrLf & "The references are " & _
"not equal.")
End If

'' declare array references
Dim secondArray As Integer()
Dim secondArrayCopy As Integer()

'' allocate secondArray and copy its reference
secondArray = New Integer() {1, 2, 3}
secondArrayCopy = secondArray

Console.WriteLine(vbCrLf & "Test passing array " & _
"reference using ByRef.")
Console.Write("Contents of secondArray before " & _
"calling SecondDouble: ")

'' print contents of secondArray before procedure call
For i = 0 To secondArray.GetUpperBound(0)
Console.Write(secondArray(i) & " ")
Next

'' pass secondArray using ByRef
SecondDouble(secondArray)

Console.Write(vbCrLf & "Contents of secondArray " & _
"after calling SecondDouble: ")

'' print contents of secondArray after procedure call
For i = 0 To secondArray.GetUpperBound(0)
Console.Write(secondArray(i) & " ")
Next

'' test whether the reference was changed by SecondDouble
If secondArray Is secondArrayCopy Then
Console.WriteLine(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLine(vbCrLf & "The references are " & _
"not equal.")
End If

End Sub '' Main

'' procedure modifies elements of array and assigns
'' new reference (note ByVal)
Sub FirstDouble(ByVal array As Integer())
Dim i As Integer

'' double each element value
For i = 0 To array.GetUpperBound(0)
array(i) *= 2
Next

'' create new reference and assign it to array
array = New Integer() {11, 12, 13}
End Sub '' FirstDouble

'' procedure modifies elements of array and assigns
'' new reference (note ByRef)
Sub SecondDouble(ByRef array As Integer())
Dim i As Integer

'' double contents of array
For i = 0 To array.GetUpperBound(0)
array(i) *= 2
Next

'' create new reference and assign it to array
array = New Integer() {11, 12, 13}
End Sub '' SecondDouble

End Module '' modPassArray

*****************************************

解决方案

Hi,

The array is passed byval. Anything you do to the array in the
subroutine will not be sent back. If you want to be able to make any
changes to the array pass it byref.

Ken
--------------------
"John Pass" <Jo******@discussions.microsoft.com> wrote in message
news:F6**********************************@microsof t.com...
Hi,
In the attached example, I do understand that the references are not changed
if an array is passed by Val. What I do not understand is the result of line
99 (If one can find this by line number) which is the last line of the
following sub routine:

'' procedure modifies elements of array and assigns
'' new reference (note ByVal)
Sub FirstDouble(ByVal array As Integer())
Dim i As Integer

'' double each element value
For i = 0 To array.GetUpperBound(0)
array(i) *= 2
Next

'' create new reference and assign it to array
array = New Integer() {11, 12, 13}
End Sub '' FirstDouble

Since the line where the values of the array ''array'' are filled by the
values 11, 12 and 13 is the later part of the same sub-routine where the
earlier changes of values in the same array took place, I would expect these
values to be printed to the screen as output. To me, it looks like the array
values being returned to the calling function were first doubled and that
simply overwritten. Apparently this does not happen.

Can anyone explain why this happens?
(The complete example is attached below

Thanks for your help,

John

*********************************

Module modArrayReferenceTest

Sub Main()
Dim i As Integer

'' declare array references
Dim firstArray As Integer()
Dim firstArrayCopy As Integer()

'' allocate firstArray and copy its reference
firstArray = New Integer() {1, 2, 3}
firstArrayCopy = firstArray

Console.WriteLine("Test passing array reference " & _
"using ByVal.")
Console.Write("Contents of firstArray before " & _
"calling FirstDouble: ")

'' print contents of firstArray
For i = 0 To firstArray.GetUpperBound(0)
Console.Write(firstArray(i) & " ")
Next

'' pass firstArray using ByVal
FirstDouble(firstArray)

Console.Write(vbCrLf & "Contents of firstArray after " & _
"calling FirstDouble: ")

'' print contents of firstArray
For i = 0 To firstArray.GetUpperBound(0)
Console.Write(firstArray(i) & " ")
Next

'' test whether reference was changed by FirstDouble
If firstArray Is firstArrayCopy Then
Console.WriteLine(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLine(vbCrLf & "The references are " & _
"not equal.")
End If

'' declare array references
Dim secondArray As Integer()
Dim secondArrayCopy As Integer()

'' allocate secondArray and copy its reference
secondArray = New Integer() {1, 2, 3}
secondArrayCopy = secondArray

Console.WriteLine(vbCrLf & "Test passing array " & _
"reference using ByRef.")
Console.Write("Contents of secondArray before " & _
"calling SecondDouble: ")

'' print contents of secondArray before procedure call
For i = 0 To secondArray.GetUpperBound(0)
Console.Write(secondArray(i) & " ")
Next

'' pass secondArray using ByRef
SecondDouble(secondArray)

Console.Write(vbCrLf & "Contents of secondArray " & _
"after calling SecondDouble: ")

'' print contents of secondArray after procedure call
For i = 0 To secondArray.GetUpperBound(0)
Console.Write(secondArray(i) & " ")
Next

'' test whether the reference was changed by SecondDouble
If secondArray Is secondArrayCopy Then
Console.WriteLine(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLine(vbCrLf & "The references are " & _
"not equal.")
End If

End Sub '' Main

'' procedure modifies elements of array and assigns
'' new reference (note ByVal)
Sub FirstDouble(ByVal array As Integer())
Dim i As Integer

'' double each element value
For i = 0 To array.GetUpperBound(0)
array(i) *= 2
Next

'' create new reference and assign it to array
array = New Integer() {11, 12, 13}
End Sub '' FirstDouble

'' procedure modifies elements of array and assigns
'' new reference (note ByRef)
Sub SecondDouble(ByRef array As Integer())
Dim i As Integer

'' double contents of array
For i = 0 To array.GetUpperBound(0)
array(i) *= 2
Next

'' create new reference and assign it to array
array = New Integer() {11, 12, 13}
End Sub '' SecondDouble

End Module '' modPassArray

*****************************************




"John Pass" <Jo******@discussions.microsoft.com> wrote in message
news:F6**********************************@microsof t.com...
:
: Hi,
: In the attached example, I do understand that the references are not
: changed if an array is passed by Val. What I do not understand is the
: result of line 99 (If one can find this by line number) which is the
: last line of the following sub routine:
:
: '' procedure modifies elements of array and assigns
: '' new reference (note ByVal)
: Sub FirstDouble(ByVal array As Integer())
: Dim i As Integer
:
: '' double each element value
: For i = 0 To array.GetUpperBound(0)
: array(i) *= 2
: Next
:
: '' create new reference and assign it to array
: array = New Integer() {11, 12, 13}
: End Sub '' FirstDouble
:
: Since the line where the values of the array ''array'' are filled by the
: values 11, 12 and 13 is the later part of the same sub-routine where
: the earlier changes of values in the same array took place, I would
: expect these values to be printed to the screen as output. To me, it
: looks like the array values being returned to the calling function
: were first doubled and that simply overwritten. Apparently this does
: not happen.
:
: Can anyone explain why this happens?
: (The complete example is attached below
:
: Thanks for your help,
:
: John
I''m going to state up front that I''m not entirely certain if my
understanding of this is correct (altho'' I believe it is or I wouldn''t
offer this post), so take this provisionally.
When you pass a reference type as a parameter into a function call, you
are passing in a reference to the memory location of that object on the
heap. The value that is passed in parameter ''array'' in functions
firstDouble and secondDouble are referneces to an instance of the array
object on the heap. Consequently, those functions can modify the data in
the array since they have a memory pointer to it.
In each function call, a new integer array is instantiated and assigned
to variable ''array''. These arrays are also on the heap and anything
method that has a reference to those objects can modify them.
As you are aware, the key difference between the two functions is that
firstDouble accepts the array parameter ''ByVal'' whereas the secondDouble
accepts the array ''ByRef''. That (as I''m also sure you are aware) is the
key to the different behaviors.
As each function creates a new array object, the reference to which is
then assigned to variable array. However, since parameter array is
passed to function firstDouble ''ByVal'', that new reference value is
discarded when the function returns and variable firstArray still
references the original array object on the heap. When secondDouble
returns however, the reference to the new integer array is assigned to
variable firstArray instead.
I''m not sure if that is any clearer, so let me try another approach.
When you reach this point in your code:

firstArray = New Integer() {1, 2, 3}
firstArrayCopy = firstArray
an array object is created on the heap with two references: ''firstArray''
and ''firstArrayCopy''. Both references are just pointers to the same
memory location where the array object resides on the heap.
When function ''firstDouble'' is initially called, a *copy* of reference
''firstArray'' is passed to the function on the stack (the object itself
is not added to the stack, but the parameter that references it is). Now
there are *3* references to a single object: ''firstArray'',
''firstArrayCopy'' (local to sub ''Main'') and ''array'' (local to function
''firstDouble''). Since function ''firstDouble'' has a reference to the
memory location of the object, it has full access to it and can modify
it.
Just prior to function ''firstDouble'' exiting, a 2nd array object is
created on the heap and the reference to that object is assigned to
variable ''array''. Now we have two independent array objects and three
references. References ''firstArray'' and ''firstArrayCopy'' still point to
the first array object and reference ''array'' points to the second.
As soon as function ''firstDouble'' exits, the reference to the 2nd array
object is on the stack. However, since it was passed in ''ByVal'', it is
discarded with no further use. Now we still have two array objects and
two references. However, references ''firstArray'' and ''firstArrayCopy''
still point to the same array object and the 2nd object (created in
function ''firstDouble'') is no longer being referenced and may be
reclaimed by the Garbage Collection process as appropriate.
For the sake of discussion, let''s ignore the first array object on the
heap and pretend there aren''t any at this point.
When you reach *this* point in your code:

secondArray = New Integer() {1, 2, 3}
secondArrayCopy = secondArray
a new array object is created on the heap, again with two references:
''secondArray'' and ''secondArrayCopy''.
Once again, when function ''secondDouble'' is initially called, a copy of
reference ''secondArray'' is passed to the function on the stack creating
3 references to that single object: ''secondArray'', ''secondArrayCopy''
and ''array''.
Just prior to function ''secondDouble'' exiting, another array object is
created on the heap and the reference to that object is assigned to
variable ''array''. As soon as function ''secondDouble'' exits, the
reference to the 2nd array object is on the stack.
*THIS* time, however, the reference was passed in ''ByRef'' and so the
reference to the new array object is copied from the stack and causes
variable ''secondArray'' to point to that object instead of the first
object. That is why when function ''secondDouble'' exits, ''secondArray''
and ''secondArrayCopy'' are no longer equal - they''re pointing to two
different objects!
Ralf


: *********************************
:
: Module modArrayReferenceTest
:
: Sub Main()
: Dim i As Integer
:
: '' declare array references
: Dim firstArray As Integer()
: Dim firstArrayCopy As Integer()
:
: '' allocate firstArray and copy its reference
: firstArray = New Integer() {1, 2, 3}
: firstArrayCopy = firstArray
:
: Console.WriteLine("Test passing array reference " & _
: "using ByVal.")
: Console.Write("Contents of firstArray before " & _
: "calling FirstDouble: ")
:
: '' print contents of firstArray
: For i = 0 To firstArray.GetUpperBound(0)
: Console.Write(firstArray(i) & " ")
: Next
:
: '' pass firstArray using ByVal
: FirstDouble(firstArray)
:
: Console.Write(vbCrLf & "Contents of firstArray after " & _
: "calling FirstDouble: ")
:
: '' print contents of firstArray
: For i = 0 To firstArray.GetUpperBound(0)
: Console.Write(firstArray(i) & " ")
: Next
:
: '' test whether reference was changed by FirstDouble
: If firstArray Is firstArrayCopy Then
: Console.WriteLine(vbCrLf & "The references are " & _
: "equal.")
: Else
: Console.WriteLine(vbCrLf & "The references are " & _
: "not equal.")
: End If
:
: '' declare array references
: Dim secondArray As Integer()
: Dim secondArrayCopy As Integer()
:
: '' allocate secondArray and copy its reference
: secondArray = New Integer() {1, 2, 3}
: secondArrayCopy = secondArray
:
: Console.WriteLine(vbCrLf & "Test passing array " & _
: "reference using ByRef.")
: Console.Write("Contents of secondArray before " & _
: "calling SecondDouble: ")
:
: '' print contents of secondArray before procedure call
: For i = 0 To secondArray.GetUpperBound(0)
: Console.Write(secondArray(i) & " ")
: Next
:
: '' pass secondArray using ByRef
: SecondDouble(secondArray)
:
: Console.Write(vbCrLf & "Contents of secondArray " & _
: "after calling SecondDouble: ")
:
: '' print contents of secondArray after procedure call
: For i = 0 To secondArray.GetUpperBound(0)
: Console.Write(secondArray(i) & " ")
: Next
:
: '' test whether the reference was changed by SecondDouble
: If secondArray Is secondArrayCopy Then
: Console.WriteLine(vbCrLf & "The references are " & _
: "equal.")
: Else
: Console.WriteLine(vbCrLf & "The references are " & _
: "not equal.")
: End If
:
: End Sub '' Main
:
: '' procedure modifies elements of array and assigns
: '' new reference (note ByVal)
: Sub FirstDouble(ByVal array As Integer())
: Dim i As Integer
:
: '' double each element value
: For i = 0 To array.GetUpperBound(0)
: array(i) *= 2
: Next
:
: '' create new reference and assign it to array
: array = New Integer() {11, 12, 13}
: End Sub '' FirstDouble
:
: '' procedure modifies elements of array and assigns
: '' new reference (note ByRef)
: Sub SecondDouble(ByRef array As Integer())
: Dim i As Integer
:
: '' double contents of array
: For i = 0 To array.GetUpperBound(0)
: array(i) *= 2
: Next
:
: '' create new reference and assign it to array
: array = New Integer() {11, 12, 13}
: End Sub '' SecondDouble
:
: End Module '' modPassArray
:
: *****************************************


"John Pass" <Jo******@discussions.microsoft.com> schrieb:

'' procedure modifies elements of array and assigns
'' new reference (note ByVal)
Sub FirstDouble(ByVal array As Integer())
Dim i As Integer

'' double each element value
For i = 0 To array.GetUpperBound(0)
array(i) *= 2
Next

'' create new reference and assign it to array
array = New Integer() {11, 12, 13}
End Sub '' FirstDouble

Since the line where the values of the array ''array'' are filled by the
values 11, 12 and 13 is the later part of the same sub-routine where the
earlier changes of values in the same array took place, I would expect
these
values to be printed to the screen as output. To me, it looks like the
array
values being returned to the calling function were first doubled and that
simply overwritten. Apparently this does not happen.



Arrays are reference types while ''Integer'' is not. Consequently an array of
integers is a reference type. By passing the array to the method using
''ByVal'' the pointer to the array gets copied and the copy is passed to the
method. Thus you can change the array''s elements, but you cannot change the
whole array. In other words, assigning a new array object to the paramater
won''t change the reference of the variable being passed to the method.
You''ll have to pass the array ''ByRef'' in order to be able to do that.

--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://classicvb.org/petition/>


这篇关于VB-101:传递数组ByVal vs ByRef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆