473,549 Members | 2,834 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

VB-101: Passing Arrays ByVal vs ByRef

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(ByV al array As Integer())
Dim i As Integer

' double each element value
For i = 0 To array.GetUpperB ound(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 modArrayReferen ceTest

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.WriteLi ne("Test passing array reference " & _
"using ByVal.")
Console.Write(" Contents of firstArray before " & _
"calling FirstDouble: ")

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' pass firstArray using ByVal
FirstDouble(fir stArray)

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

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' test whether reference was changed by FirstDouble
If firstArray Is firstArrayCopy Then
Console.WriteLi ne(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLi ne(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.WriteLi ne(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.Get UpperBound(0)
Console.Write(s econdArray(i) & " ")
Next

' pass secondArray using ByRef
SecondDouble(se condArray)

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

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

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

End Sub ' Main

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

' double each element value
For i = 0 To array.GetUpperB ound(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(By Ref array As Integer())
Dim i As Integer

' double contents of array
For i = 0 To array.GetUpperB ound(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

*************** *************** ***********
Nov 21 '05 #1
11 8101
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******@discu ssions.microsof t.com> wrote in message
news:F6******** *************** ***********@mic rosoft.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(ByV al array As Integer())
Dim i As Integer

' double each element value
For i = 0 To array.GetUpperB ound(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 modArrayReferen ceTest

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.WriteLi ne("Test passing array reference " & _
"using ByVal.")
Console.Write(" Contents of firstArray before " & _
"calling FirstDouble: ")

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' pass firstArray using ByVal
FirstDouble(fir stArray)

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

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' test whether reference was changed by FirstDouble
If firstArray Is firstArrayCopy Then
Console.WriteLi ne(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLi ne(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.WriteLi ne(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.Get UpperBound(0)
Console.Write(s econdArray(i) & " ")
Next

' pass secondArray using ByRef
SecondDouble(se condArray)

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

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

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

End Sub ' Main

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

' double each element value
For i = 0 To array.GetUpperB ound(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(By Ref array As Integer())
Dim i As Integer

' double contents of array
For i = 0 To array.GetUpperB ound(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

*************** *************** ***********
Nov 21 '05 #2


"John Pass" <Jo******@discu ssions.microsof t.com> wrote in message
news:F6******** *************** ***********@mic rosoft.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(ByV al array As Integer())
: Dim i As Integer
:
: ' double each element value
: For i = 0 To array.GetUpperB ound(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 'secondArrayCop y'.
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', 'secondArrayCop y'
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 'secondArrayCop y' are no longer equal - they're pointing to two
different objects!
Ralf


: *************** *************** ***
:
: Module modArrayReferen ceTest
:
: 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.WriteLi ne("Test passing array reference " & _
: "using ByVal.")
: Console.Write(" Contents of firstArray before " & _
: "calling FirstDouble: ")
:
: ' print contents of firstArray
: For i = 0 To firstArray.GetU pperBound(0)
: Console.Write(f irstArray(i) & " ")
: Next
:
: ' pass firstArray using ByVal
: FirstDouble(fir stArray)
:
: Console.Write(v bCrLf & "Contents of firstArray after " & _
: "calling FirstDouble: ")
:
: ' print contents of firstArray
: For i = 0 To firstArray.GetU pperBound(0)
: Console.Write(f irstArray(i) & " ")
: Next
:
: ' test whether reference was changed by FirstDouble
: If firstArray Is firstArrayCopy Then
: Console.WriteLi ne(vbCrLf & "The references are " & _
: "equal.")
: Else
: Console.WriteLi ne(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.WriteLi ne(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.Get UpperBound(0)
: Console.Write(s econdArray(i) & " ")
: Next
:
: ' pass secondArray using ByRef
: SecondDouble(se condArray)
:
: Console.Write(v bCrLf & "Contents of secondArray " & _
: "after calling SecondDouble: ")
:
: ' print contents of secondArray after procedure call
: For i = 0 To secondArray.Get UpperBound(0)
: Console.Write(s econdArray(i) & " ")
: Next
:
: ' test whether the reference was changed by SecondDouble
: If secondArray Is secondArrayCopy Then
: Console.WriteLi ne(vbCrLf & "The references are " & _
: "equal.")
: Else
: Console.WriteLi ne(vbCrLf & "The references are " & _
: "not equal.")
: End If
:
: End Sub ' Main
:
: ' procedure modifies elements of array and assigns
: ' new reference (note ByVal)
: Sub FirstDouble(ByV al array As Integer())
: Dim i As Integer
:
: ' double each element value
: For i = 0 To array.GetUpperB ound(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(By Ref array As Integer())
: Dim i As Integer
:
: ' double contents of array
: For i = 0 To array.GetUpperB ound(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
:
: *************** *************** ***********
Nov 21 '05 #3
"John Pass" <Jo******@discu ssions.microsof t.com> schrieb:
' procedure modifies elements of array and assigns
' new reference (note ByVal)
Sub FirstDouble(ByV al array As Integer())
Dim i As Integer

' double each element value
For i = 0 To array.GetUpperB ound(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/>

Nov 21 '05 #4
Passing an array byval is exactly like passing any other object byval - any
change to the object internals is seen in the calling code. So *every*
change except any change to the actual array object pointer *is* sent back.

David Anton
www.tangiblesoftwaresolutions.com
Home of the Instant C# VB.NET to C# converter
and the Instant VB C# to VB.NET converter

"Ken Tucker [MVP]" wrote:
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******@discu ssions.microsof t.com> wrote in message
news:F6******** *************** ***********@mic rosoft.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(ByV al array As Integer())
Dim i As Integer

' double each element value
For i = 0 To array.GetUpperB ound(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 modArrayReferen ceTest

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.WriteLi ne("Test passing array reference " & _
"using ByVal.")
Console.Write(" Contents of firstArray before " & _
"calling FirstDouble: ")

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' pass firstArray using ByVal
FirstDouble(fir stArray)

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

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' test whether reference was changed by FirstDouble
If firstArray Is firstArrayCopy Then
Console.WriteLi ne(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLi ne(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.WriteLi ne(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.Get UpperBound(0)
Console.Write(s econdArray(i) & " ")
Next

' pass secondArray using ByRef
SecondDouble(se condArray)

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

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

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

End Sub ' Main

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

' double each element value
For i = 0 To array.GetUpperB ound(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(By Ref array As Integer())
Dim i As Integer

' double contents of array
For i = 0 To array.GetUpperB ound(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

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

Nov 21 '05 #5
Ralf,
I very much appreciate your detailed explanation and I think I now
understand it (better), but it also opens new questions.

As I wrote originally, I already did understand that the Ref type parameter,
if passed ByVal, does not change the original array data in memory, because
it only points to and changes the value of an (other) instance of the same
array. My question was about why the change made in the 1st part of the sub
firstDouble (ByVal ...) made an effective change to the output printed to
screen, while the changes made in the 2nd part of the same sub had no effect.

I understand from your explanation that the code in the 2nd part of this sub
('array = New array() {11, 12, 13}' creates a completely new object. If that
is indeed the case, I would fully understand it!
But that would mean that there would be two different array objects with the
exact same name 'array', containing the same data of the same data type. That
sounds odd. How would the software be able to distinguish between the two?

New question triggered by your explanation:
You state that by using the code:
Dim firstArray As Integer()
Dim firstArrayCopy As Integer()
"an (one?) array object is created on the heap with two references".
Thus far I understood that this code would create two array objects with
identical content but different names for firstArray and firstArrayCopy, but
that the array 'array' as used in the procedures FirstDouble() and
SecondDouble() would be a reference to firstArray and not a new object. If
indeed one object with two refernces is created, for firstArray and
firstArrayCopy followed by a change of the array values, could it still be
one object with two instances? So far I cannot see how that is possible.

Thanks for you explanation,

John

"_AnonCowar d" wrote:


"John Pass" <Jo******@discu ssions.microsof t.com> wrote in message
news:F6******** *************** ***********@mic rosoft.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(ByV al array As Integer())
: Dim i As Integer
:
: ' double each element value
: For i = 0 To array.GetUpperB ound(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 'secondArrayCop y'.
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', 'secondArrayCop y'
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 'secondArrayCop y' are no longer equal - they're pointing to two
different objects!
Ralf


: *************** *************** ***
:
: Module modArrayReferen ceTest
:
: 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.WriteLi ne("Test passing array reference " & _
: "using ByVal.")
: Console.Write(" Contents of firstArray before " & _
: "calling FirstDouble: ")
:
: ' print contents of firstArray
: For i = 0 To firstArray.GetU pperBound(0)
: Console.Write(f irstArray(i) & " ")
: Next
:
: ' pass firstArray using ByVal
: FirstDouble(fir stArray)
:
: Console.Write(v bCrLf & "Contents of firstArray after " & _
: "calling FirstDouble: ")
:
: ' print contents of firstArray
: For i = 0 To firstArray.GetU pperBound(0)
: Console.Write(f irstArray(i) & " ")
: Next
:
: ' test whether reference was changed by FirstDouble
: If firstArray Is firstArrayCopy Then
: Console.WriteLi ne(vbCrLf & "The references are " & _
: "equal.")
: Else
: Console.WriteLi ne(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.WriteLi ne(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.Get UpperBound(0)
: Console.Write(s econdArray(i) & " ")
: Next
:
: ' pass secondArray using ByRef
: SecondDouble(se condArray)
:
: Console.Write(v bCrLf & "Contents of secondArray " & _
: "after calling SecondDouble: ")
:
: ' print contents of secondArray after procedure call
: For i = 0 To secondArray.Get UpperBound(0)
: Console.Write(s econdArray(i) & " ")
: Next
:
: ' test whether the reference was changed by SecondDouble
: If secondArray Is secondArrayCopy Then
: Console.WriteLi ne(vbCrLf & "The references are " & _
: "equal.")
: Else
: Console.WriteLi ne(vbCrLf & "The references are " & _
: "not equal.")
: End If
:
: End Sub ' Main
:
: ' procedure modifies elements of array and assigns
: ' new reference (note ByVal)
: Sub FirstDouble(ByV al array As Integer())
: Dim i As Integer
:
: ' double each element value
: For i = 0 To array.GetUpperB ound(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(By Ref array As Integer())
: Dim i As Integer
:
: ' double contents of array
: For i = 0 To array.GetUpperB ound(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
:
: *************** *************** ***********

Nov 21 '05 #6
Herfried, Thanks for your explanation as well.

You write: 'assigning a new array object to the paramater
won't change the reference of the variable being passed to the method'.

Do you mean that for the code section of line 99? :
'array = New Integer() {11, 12, 13}'
That would mean that a new object is created rather than the old one's data
are overwritten.

Please also look at my longer response to _AnonCoward.

Thanks for your explanation,

John


"Herfried K. Wagner [MVP]" wrote:
"John Pass" <Jo******@discu ssions.microsof t.com> schrieb:
' procedure modifies elements of array and assigns
' new reference (note ByVal)
Sub FirstDouble(ByV al array As Integer())
Dim i As Integer

' double each element value
For i = 0 To array.GetUpperB ound(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/>

Nov 21 '05 #7
Ken, Thanks for your response.
My questions was why the 2nd part of the sub did not change the changes the
output to screen while the 1st part did.
Please see my (longer) resonse to _AnonCoward.

Regards,

John.

"Ken Tucker [MVP]" wrote:
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******@discu ssions.microsof t.com> wrote in message
news:F6******** *************** ***********@mic rosoft.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(ByV al array As Integer())
Dim i As Integer

' double each element value
For i = 0 To array.GetUpperB ound(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 modArrayReferen ceTest

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.WriteLi ne("Test passing array reference " & _
"using ByVal.")
Console.Write(" Contents of firstArray before " & _
"calling FirstDouble: ")

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' pass firstArray using ByVal
FirstDouble(fir stArray)

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

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' test whether reference was changed by FirstDouble
If firstArray Is firstArrayCopy Then
Console.WriteLi ne(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLi ne(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.WriteLi ne(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.Get UpperBound(0)
Console.Write(s econdArray(i) & " ")
Next

' pass secondArray using ByRef
SecondDouble(se condArray)

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

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

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

End Sub ' Main

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

' double each element value
For i = 0 To array.GetUpperB ound(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(By Ref array As Integer())
Dim i As Integer

' double contents of array
For i = 0 To array.GetUpperB ound(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

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

Nov 21 '05 #8
"John Pass" <Jo******@discu ssions.microsof t.com> schrieb:
You write: 'assigning a new array object to the paramater
won't change the reference of the variable being passed to the method'.

Do you mean that for the code section of line 99? :
'array = New Integer() {11, 12, 13}'
That would mean that a new object is created rather than the old one's
data
are overwritten.


Yes. You are creating a new array and assign it to the method's parameter.
If the parameter is passed 'ByVal', the array passed to the method in the
parameter is not changed, because you are assigning the new array to a
temporary copy of the array pointer passed to the method.

\\\
Public Sub Foo1(ByVal Bla() As Integer)
Bla = New Integer() {10, 20}
End Sub

Public Sub Foo2(ByRef Bla() As Integer)
Bla = New Integer() {10, 20}
End Sub
..
..
..
Dim a() As Integer = {1, 2}
Foo1(a)

' 'a' still points to the array containing {1, 2}.

Foo2(a)

' 'a' points to the array containing {10, 20}.
///

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

Nov 21 '05 #9
David, Thanks for your response.
My real questions was why the 2nd part of the sub did not change the changes
the output to screen while the 1st part did.
If every change is sent back, why not the changes made by the 2nd part of
the sub.
Please see my (longer) response to _AnonCoward.

Regards,

John

"David Anton" wrote:
Passing an array byval is exactly like passing any other object byval - any
change to the object internals is seen in the calling code. So *every*
change except any change to the actual array object pointer *is* sent back.

David Anton
www.tangiblesoftwaresolutions.com
Home of the Instant C# VB.NET to C# converter
and the Instant VB C# to VB.NET converter

"Ken Tucker [MVP]" wrote:
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******@discu ssions.microsof t.com> wrote in message
news:F6******** *************** ***********@mic rosoft.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(ByV al array As Integer())
Dim i As Integer

' double each element value
For i = 0 To array.GetUpperB ound(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 modArrayReferen ceTest

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.WriteLi ne("Test passing array reference " & _
"using ByVal.")
Console.Write(" Contents of firstArray before " & _
"calling FirstDouble: ")

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' pass firstArray using ByVal
FirstDouble(fir stArray)

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

' print contents of firstArray
For i = 0 To firstArray.GetU pperBound(0)
Console.Write(f irstArray(i) & " ")
Next

' test whether reference was changed by FirstDouble
If firstArray Is firstArrayCopy Then
Console.WriteLi ne(vbCrLf & "The references are " & _
"equal.")
Else
Console.WriteLi ne(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.WriteLi ne(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.Get UpperBound(0)
Console.Write(s econdArray(i) & " ")
Next

' pass secondArray using ByRef
SecondDouble(se condArray)

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

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

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

End Sub ' Main

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

' double each element value
For i = 0 To array.GetUpperB ound(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(By Ref array As Integer())
Dim i As Integer

' double contents of array
For i = 0 To array.GetUpperB ound(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

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

Nov 21 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
486
by: Terry | last post by:
Hi, I need some feedback. We are converting to .Net and we are trying to decide on whether to use VB.net or C#.net. As far as our current systems, they will probably be rewritten in ASP.Net. I have looked into both and I don't see anything that would scream out to use one or the other. So at this point, it is still a toss up. However, I want...
13
5134
by: Arsalan | last post by:
Is there any advantage in C# over VB.NET ? Or the difference is only syntax ? Can anything done in C# which cannot be done in VB.NET?
72
3424
by: Robin Tucker | last post by:
I need to find some documents/research for my manager about VB.NET v C# use. I've noticed that there are many more people using C# than VB.NET, that there seem to be more job vacancies specifying C# and projects written with it. I would basically like any links you might have to articles with non-anecdotal evidence for usage patterns, if...
34
3129
by: Eric Wise | last post by:
Does anyone work for companies that actually implement both VB and C#? I know that you can do this in theory, I just find it hard to imagine that a company would split its programming technologies like that. Of course now with the CLR there doesn't seem to be any performance benefit to using C# over VB, and VB I think is an "easier"...
12
1646
by: Leo Muller | last post by:
I always thought that moving from VB.NET to C# would be very easy. Even though so far it hasn't been hard, there are some annoying things, that may have to do with my visual studio settings. - When I type "system." the intellisense doesn't comlete this, only if I write it with a capital S, rather annoying... - is the type "string" or...
182
7407
by: Jim Hubbard | last post by:
http://www.eweek.com/article2/0,1759,1774642,00.asp
25
1806
by: Sharrukin Amiri | last post by:
Hello, I am using VB 6.0 for many years. Everytime I needed to build software applications, I just opened VB 6.0 and started coding. I am now looking VB.NET Express Edition and I find I can no longer do this very easily. I find that there is too much copy and paste of code in order to get an app running. I also find it slow. Is it me...
2
1677
by: D H | last post by:
Hi, Hi, I was looking for your opinion on VB.NET - its long-term prospects, etc. Sorry this is vague, but it's not meant to be a troll. It's a pro-VB.NET post actually. I haven't used VB or VB.NET really, but I have used Realbasic (a vb clone), Java, C#, C, and Python. I work in education, and I'd like something that is easy enough for...
39
2509
by: clintonG | last post by:
This is not about starting a fight but an observation that seems to be proving itself on its own merit and is therefore simply a point of conjecture. I did not get serious about writing software until I learned ASP/VBS (if that can be called writing software) as my focus was and remains for the most part developing for the web. Even though...
0
7751
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7992
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7511
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7840
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6088
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5396
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3509
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1973
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
793
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.