Xtreme Visual Basic Talk

Xtreme Visual Basic Talk (http://www.xtremevbtalk.com/)
-   .NET Communications (http://www.xtremevbtalk.com/-net-communications/)
-   -   When is an array a reference and when is it a copy? (http://www.xtremevbtalk.com/-net-communications/327272-array-reference-copy.html)

naton 09-17-2014 05:23 AM

When is an array a reference and when is it a copy?
 
Hi there,

I'm slightly confused regarding when an array is a reference (i.e. a pointer) and when it is a copy.

Please read the comments in the code below and help me understand the code's behavior.

Thanks

Code:

    Public Sub Main()
        Dim arr1() As Double = {1, 2, 3}
        Dim myObject As someClass = New someClass(arr1)

        ' The array Arr2() is a copy of array Arr1(). Isn't it?
        Dim arr2() As Double = arr1

        ' I don't understand why below arr4() is a copy of aray arr3().
        ' I thought that arr4 is a pointer to arr3?

        Dim arr3(3) As someClass

        For i As Integer = 0 To 3
            arr3(i) = New someClass(arr1)
        Next

        Dim arr4() As someClass = arr3

        ' Here I don't understand why arr4(4) is a pointer to arr(5)?
        ReDim Preserve arr4(4)
        Dim arr5() As Double = {4, 2, 6, 9}
        arr4(4) = New someClass(arr5)

        arr5(0) = 0.001
    End Sub

    Private Class someClass
        Private mArray() As Double

        Public Sub New(ByVal a() As Double)
            ' Why is it that mArray is a reference of a() and not a copy of a()?
            mArray = a
        End Sub

        Public Property SetGetArray() As Double()
            Get
                ' Why is it that the returned array here is a copy and not a reference to mArray()?
                Return mArray
            End Get
            Set(ByVal a() As Double)
                ' Is mArray() a reference or a copy of a()?
                mArray = a
            End Set
        End Property
    End Class


PlausiblyDamp 09-17-2014 06:13 AM

Quote:

' The array Arr2() is a copy of array Arr1(). Isn't it?
Dim arr2() As Double = arr1
Nope, arr2 and arr1 are simply references to the same in memory data structure - if you change an item in arr1 then you will see the change reflected in arr2

Quote:

' I don't understand why below arr4() is a copy of aray arr3().
' I thought that arr4 is a pointer to arr3?
Dim arr3(3) As someClass

For i As Integer = 0 To 3
arr3(i) = New someClass(arr1)
Next
In this case you are declaring an array of someClass and then creating four instances of this type and passing arr1 into all of them - again though everything is pointing to the same memory structure, if you change arr1, arr2 or the array contained by any of the items in arr3 you will see all of them change.

Quote:

Dim arr4() As someClass = arr3
The variable arr4 is just a pointer to arr3 - again if you edit any of the items you will see it reflected in all of the items.

The simple rule is that types under .Net are either a ValueType (Structure) or a ReferenceType (Class), if it is a reference type then all direct assignments are done as references. This can be seen in all of the assignments in your code, if you need a copy then you need to take deliberate action (such as an implementation of ICloneable or using Linq's .ToArray etc)

When you look at the final bit of your code
Quote:

ReDim Preserve arr4(4)
Dim arr5() As Double = {4, 2, 6, 9}
arr4(4) = New someClass(arr5)

arr5(0) = 0.001
the reason it is a reference is the fact you are dealing with reference types, this isn't any different to the rest of the posted code. Try stepping through the code in a debugger and change the various references to the array and you will see this is consistent behaviour.

Also if you look at the code in someClass and again use it under a debugger you will see that all the occasions you are using mArray are references, if you assign the result of SetGetArray to a variable and then change one of the values you will again see this reflected in all variables that are referencing the original array.

TL;DR answer - it is always a reference unless you deliberately make a copy.

naton 09-17-2014 08:27 AM

PlausiblyDamp, thanks for your detailed reply. So basically my initial way of thinking before opening this thread was correct. Unless doing a deep copy the arrays in the code are simple references.

I admit I got a little confused and this is the section of the code that confused me. Although arr4 is a reference for arr3, increasing the size of arr4 is not reflacted back into arr3. After using "Redim Preserve", the debbuger shows that the size of arr4 increases by 1 while the size of arr3 remains the same.

Code:

    ReDim Preserve arr4(4)
    Dim arr5() As Double = {4, 2, 6, 9}
    arr4(4) = New someClass(arr5)

I've just remembered how Redim works. It reserves a new memory chunck and make the original variable, in this instance arr4, point to it.

It seems that :
- arr4(0) points to same memory as arr3(0),
- arr4(1) points to same memory as arr3(1)
- arr4(2) points to same memory as arr3(2)
- arr4(3) points to same memory as arr3(3)
- arr4(4) points to a new memory location created by "Redim".

correct?

Thanks.

PlausiblyDamp 09-17-2014 02:10 PM

As far as I am aware Redim Preserve makes a new array of the new size and copies the old array into this new array, looking with ildasm.exe it does indeed show a call to System.Array.CopyArray.

Because you are copying an array of reference types the new array contains a separate copy of the data, however the original data was nothing more than a bunch of references to where the original instances of someClass are located in memory. At this point arr1, arr2 and arr3 are all pointing to the same array structure in memory- the one created when arr1 was instantiated. arr4 however is a new array containing a copy of the contents of the original array plus an additional free slot. The existing items that were copied over though are just pointers to the original instances of someClass

naton 09-18-2014 03:18 AM

Are those diagrams correct?

http://oi61.tinypic.com/ifrbd3.jpg

PlausiblyDamp 09-18-2014 09:32 AM

Link seems to be broken, just getting an error page. You could just attach the image to the post rather than using a third party host.

naton 09-19-2014 09:56 AM

1 Attachment(s)
I didn't see the attachment button before. It is done now :)

By the way, is there any neat trick to display only one column of a multi-dimensional array in the debugger?

The link below show how how it is done for a C++ code:
http://stackoverflow.com/questions/1...ng-in-visual-c

PlausiblyDamp 09-19-2014 10:12 AM

That diagram looks pretty much spot on. Not sure if there is an easy way of doing that in the debugger, I shall have a look though and see what I find.

naton 09-21-2014 05:50 AM

thank you.


All times are GMT -6. The time now is 03:40 AM.

Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Search Engine Optimisation provided by DragonByte SEO v2.0.15 (Lite) - vBulletin Mods & Addons Copyright © 2017 DragonByte Technologies Ltd.
All site content is protected by the Digital Millenium Act of 1998. Copyright©2001-2011 MAS Media Inc. and Extreme Visual Basic Forum. All rights reserved.
You may not copy or reproduce any portion of this site without written consent.