Home All Groups Group Topic Archive Search About

Copy Constructor needed in VB.NET 2.0?

Author
8 Jun 2009 3:05 PM
Joe Duchtel
Hello -

I always thought that if I wanted a deep copy of an object, that I
needed to implement a copy constructor.  However, I tried the
following code in VB.NET 2.0 and it worked just fine ...

Public Class cTestClassA
    Protected mData As New ArrayList

    Public Sub New(ByVal aNumber As Integer)
        For i As Integer = 1 To aNumber
            mData.Add(New cTestClassB(i.ToString))
        Next
    End Sub

    Public Sub printData()
        For i As Integer = 0 To mData.Count - 1
            Console.WriteLine(CType(mData(i), cTestClassB).getData())
        Next
    End Sub
End Class

Public Class cTestClassB
    Protected mName As String

    Public Function getData() As String
        Return mName
    End Function

    Public Sub New(ByVal aName As String)
        mName = aName
    End Sub
End Class

Sub Main(ByVal aCommandArguments() As String)
    Dim lA As New cTestClassA(2)

    lA.printData()

    Dim lB As cTestClassA = lA   ' <<<

    lB.printData()

I thought that for the <<< assignment needed to be done via a copy
constructor but apparently not.

Can I rely on .NET to always create a deep copy?  Am I missing
something?

Thanks,
Joe

Author
8 Jun 2009 3:26 PM
Armin Zingler
Joe Duchtel wrote:
> Hello -
>
> I always thought that if I wanted a deep copy of an object, that I
> needed to implement a copy constructor.  However, I tried the
> following code in VB.NET 2.0 and it worked just fine ...


Which version is VB.Net 2.0? The latest version is version 9, product name
VB 2008. Probably you mean Framework 2.0.

> Public Class cTestClassA
>    Protected mData As New ArrayList

I'd recommend replacing the Arraylist by a List(Of).


Show quoteHide quote
>    Public Sub New(ByVal aNumber As Integer)
>        For i As Integer = 1 To aNumber
>            mData.Add(New cTestClassB(i.ToString))
>        Next
>    End Sub
>
>    Public Sub printData()
>        For i As Integer = 0 To mData.Count - 1
>            Console.WriteLine(CType(mData(i), cTestClassB).getData())
>        Next
>    End Sub
> End Class
>
> Public Class cTestClassB
>    Protected mName As String
>
>    Public Function getData() As String
>        Return mName
>    End Function
>
>    Public Sub New(ByVal aName As String)
>        mName = aName
>    End Sub
> End Class
>
> Sub Main(ByVal aCommandArguments() As String)
>    Dim lA As New cTestClassA(2)
>
>    lA.printData()
>
>    Dim lB As cTestClassA = lA   ' <<<
>
>    lB.printData()
>
> I thought that for the <<< assignment needed to be done via a copy
> constructor but apparently not.
>
> Can I rely on .NET to always create a deep copy?  Am I missing
> something?

A class is a reference type. The assignment copies the variable content.
The content is a reference to an object. Now you have two references to the
same object. You do not have two objects.


Armin
Author
8 Jun 2009 6:33 PM
Cor Ligthert[MVP]
Armin

I put this to you simply  because it is written in this messagethread but I
see it nowhere named and I assume you know it.

This kind of copy is called a shallow copy something I can only remember
because a squello is a shark in Italian and I say that mostly in the same
way as shallow.

Cor
Author
8 Jun 2009 9:00 PM
dunawayc
On Jun 8, 1:33 pm, "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl>
wrote:
> Armin
>
> I put this to you simply  because it is written in this messagethread but I
> see it nowhere named and I assume you know it.
>
> This kind of copy is called a shallow copy something I can only remember
> because a squello is a shark in Italian and I say that mostly in the same
> way as shallow.
>
> Cor

I don't think that is even a shallow copy.  A shallow copy results in
2 separate instances with all value type properties copied, but for
reference type properties, only the reference is copied.  A deep copy
will result in true copies of all value type properties and reference
type properties.

Chris
Author
8 Jun 2009 10:50 PM
Cor Ligthert[MVP]
Chris,

This wrote Armin

> A class is a reference type. The assignment copies the variable content.
> The content is a reference to an object. Now you have two references to
> the
> same object. You do not have two objects.
>
>> I don't think that is even a shallow copy.  A shallow copy results in
>> 2 separate instances with all value type properties copied, but for
>> reference type properties, only the reference is copied.

What is the difference?

He did not write about the valuetypes, but that is in my idea not the
essential part from a Shallow copy.

Cor




<dunaw***@gmail.com> wrote in message
Show quoteHide quote
news:57336bbe-0d2a-4645-8e0a-cee415743268@k20g2000vbp.googlegroups.com...
> On Jun 8, 1:33 pm, "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl>
> wrote:
>> Armin
>>
>> I put this to you simply  because it is written in this messagethread but
>> I
>> see it nowhere named and I assume you know it.
>>
>> This kind of copy is called a shallow copy something I can only remember
>> because a squello is a shark in Italian and I say that mostly in the same
>> way as shallow.
>>
>> Cor
>
> I don't think that is even a shallow copy.  A shallow copy results in
> 2 separate instances with all value type properties copied, but for
> reference type properties, only the reference is copied.  A deep copy
> will result in true copies of all value type properties and reference
> type properties.
>
> Chris
Author
8 Jun 2009 10:29 PM
James Hahn
This is not a shallow copy.  A shallow copy is a method of copying an object
in which the fields are copied as their bit values - value-type fields as
the bit value of their current value and reference-type fields as the bit
value of their references.  This is in contrast to a deep copy where
value-type fields are copied as their bit values but reference type fields
are copied as references to objects which are copies (new instances) of the
original objects that were referenced by those fields (recursively as
required).

Show quoteHide quote
"Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl> wrote in message
news:utc0veG6JHA.2456@TK2MSFTNGP02.phx.gbl...
> Armin
>
> I put this to you simply  because it is written in this messagethread but
> I see it nowhere named and I assume you know it.
>
> This kind of copy is called a shallow copy something I can only remember
> because a squello is a shark in Italian and I say that mostly in the same
> way as shallow.
>
> Cor
Author
8 Jun 2009 3:27 PM
Joe Duchtel
On Jun 8, 11:05 am, Joe Duchtel <duch***@gmail.com> wrote:
Show quoteHide quote
> Hello -
>
> I always thought that if I wanted a deep copy of an object, that I
> needed to implement a copy constructor.  However, I tried the
> following code in VB.NET 2.0 and it worked just fine ...
>
> Public Class cTestClassA
>     Protected mData As New ArrayList
>
>     Public Sub New(ByVal aNumber As Integer)
>         For i As Integer = 1 To aNumber
>             mData.Add(New cTestClassB(i.ToString))
>         Next
>     End Sub
>
>     Public Sub printData()
>         For i As Integer = 0 To mData.Count - 1
>             Console.WriteLine(CType(mData(i), cTestClassB).getData())
>         Next
>     End Sub
> End Class
>
> Public Class cTestClassB
>     Protected mName As String
>
>     Public Function getData() As String
>         Return mName
>     End Function
>
>     Public Sub New(ByVal aName As String)
>         mName = aName
>     End Sub
> End Class
>
> Sub Main(ByVal aCommandArguments() As String)
>     Dim lA As New cTestClassA(2)
>
>     lA.printData()
>
>     Dim lB As cTestClassA = lA   ' <<<
>
>     lB.printData()
>
> I thought that for the <<< assignment needed to be done via a copy
> constructor but apparently not.
>
> Can I rely on .NET to always create a deep copy?  Am I missing
> something?
>
> Thanks,
> Joe

Hello -

Okay ... I just figured out what I did wrong.  I did not create a new
instance of cTestClassA when creating lB.  So there is a need for a
copy constructor.

The only question I have is why the following will not call the copy
constructor ...
Dim lB As New cTestClassA()
lB = lA
.... whereas this works ...
Dim lB As New cTestClassA(lA)

Thanks!
Joe
Author
8 Jun 2009 10:35 PM
James Hahn
In the first case you are simply creating a new reference to the object and
no copying is involved.

In the second case the constructor for cTestClassA is being invoked, and
presumably this constructor includes the copy operation for the case where
an existing instance is passed as an argument.

"Joe Duchtel" <duch***@gmail.com> wrote in message
news:8eae3043-e4e6-4a03-8ded-b0c9eba72471@j12g2000vbl.googlegroups.com...
On Jun 8, 11:05 am, Joe Duchtel <duch***@gmail.com> wrote:
> snip <

Hello -

Okay ... I just figured out what I did wrong.  I did not create a new
instance of cTestClassA when creating lB.  So there is a need for a
copy constructor.

The only question I have is why the following will not call the copy
constructor ...
Dim lB As New cTestClassA()
lB = lA
.... whereas this works ...
Dim lB As New cTestClassA(lA)

Thanks!
Joe
Author
8 Jun 2009 3:32 PM
OmegaSquared
Hello, Joe,

Actually, you are not making a copy.  You are merely assigning a reference. 
That is, IA and IB both refer to the same object.  If you add the line:

    Console.WriteLine(IA Is IB)

after "lB.printData()" you should get the result "True".

Cheers,
Randy
Author
8 Jun 2009 4:02 PM
Mike
Joe Duchtel wrote:
> Hello -
>
> I always thought that if I wanted a deep copy of an object, that I
> needed to implement a copy constructor.  However, I tried the
> following code in VB.NET 2.0 and it worked just fine ...
>
> ....
>
> I thought that for the <<< assignment needed to be done via a copy
> constructor but apparently not.
>
> Can I rely on .NET to always create a deep copy?  Am I missing
> something?

To me, that isn't doing any copying at all.

What you really have above:

     Dim lB As cTestClassA = lA

where lB is a pointer to the lA instantiated pointer to cTestClassA
object.

In C/C++, it would akin to:

     cTestClassA *lA = new cTestClassA(2)
     cTestClassA *lB = 1A

Now, whether you are missing something depending on what you thinking
overall. :-)

For me, the VB.NET constructor concept is different than like in most
OOPs concepts - the ctor is called whether you use NEW or not.

So in C/C++, what you would be referring to is is this idea:

      cTestClassA lA(2)
      cTestClassA lB = 1A

and in this case, there is a COPY concept going on.  The compiler
handles its it for you but more importantly, the CTOR is being called.

It a critical difference for people coming to VB.NET from the C/C++
language.

    DIM var as NATURAL_TYPE              << NOT A POINTER
    DIM var as STRUCTURE_CLASS_TYPE      << UNINITIALIZED POINTER
    DIM var as NEW STRUCTURE_CLASS_TYPE  << INITIALIZED POINTER

To prove this, all you need to see what the pointer addresses are for
the mdata items or I think you can use the inherited Equal method to
see if the addresses (object references) are the same.

         WriteLine(" OBJECT EQUALS: {0}", lA.Equals(lB))
         WriteLine(" DATA EQUALS: {0}", lA.mData.Equals(lB.mData))

For this test, change the protected mData to public.

I see true here, that is not a copy, but a reference.  A copy would be
that they would have different pointers.

---
Author
8 Jun 2009 4:03 PM
Tom Shelton
On 2009-06-08, Joe Duchtel <duch***@gmail.com> wrote:
Show quoteHide quote
> Hello -
>
> I always thought that if I wanted a deep copy of an object, that I
> needed to implement a copy constructor.  However, I tried the
> following code in VB.NET 2.0 and it worked just fine ...
>
> Public Class cTestClassA
>     Protected mData As New ArrayList
>
>     Public Sub New(ByVal aNumber As Integer)
>         For i As Integer = 1 To aNumber
>             mData.Add(New cTestClassB(i.ToString))
>         Next
>     End Sub
>
>     Public Sub printData()
>         For i As Integer = 0 To mData.Count - 1
>             Console.WriteLine(CType(mData(i), cTestClassB).getData())
>         Next
>     End Sub
> End Class
>
> Public Class cTestClassB
>     Protected mName As String
>
>     Public Function getData() As String
>         Return mName
>     End Function
>
>     Public Sub New(ByVal aName As String)
>         mName = aName
>     End Sub
> End Class
>
> Sub Main(ByVal aCommandArguments() As String)
>     Dim lA As New cTestClassA(2)
>
>     lA.printData()
>
>     Dim lB As cTestClassA = lA   ' <<<
>
>     lB.printData()
>
> I thought that for the <<< assignment needed to be done via a copy
> constructor but apparently not.
>
> Can I rely on .NET to always create a deep copy?  Am I missing
> something?
>
> Thanks,
> Joe

You have simply caused two variables to reference the same object.  No copy of
the object is made.  Simply alter the data in one instance, and you will see
that boht objects are altered.

There is no concept of an automatic copy constructor in .NET.  If you want to
create one, you can - but, it will not be automatically called.  The normal
way to implement the concept of deep copy in .NET is to implement IClonable.
Then clients can call the .Clone method when they want a deep copy of your
object.


--
Tom Shelton
Author
8 Jun 2009 4:13 PM
Joe Duchtel
On Jun 8, 12:03 pm, Tom Shelton <tom_shel***@comcastXXXXXXX.net>
wrote:
Show quoteHide quote
> On 2009-06-08, Joe Duchtel <duch***@gmail.com> wrote:
>
>
>
>
>
> > Hello -
>
> > I always thought that if I wanted a deep copy of an object, that I
> > needed to implement a copy constructor.  However, I tried the
> > following code in VB.NET 2.0 and it worked just fine ...
>
> > Public Class cTestClassA
> >     Protected mData As New ArrayList
>
> >     Public Sub New(ByVal aNumber As Integer)
> >         For i As Integer = 1 To aNumber
> >             mData.Add(New cTestClassB(i.ToString))
> >         Next
> >     End Sub
>
> >     Public Sub printData()
> >         For i As Integer = 0 To mData.Count - 1
> >             Console.WriteLine(CType(mData(i), cTestClassB).getData())
> >         Next
> >     End Sub
> > End Class
>
> > Public Class cTestClassB
> >     Protected mName As String
>
> >     Public Function getData() As String
> >         Return mName
> >     End Function
>
> >     Public Sub New(ByVal aName As String)
> >         mName = aName
> >     End Sub
> > End Class
>
> > Sub Main(ByVal aCommandArguments() As String)
> >     Dim lA As New cTestClassA(2)
>
> >     lA.printData()
>
> >     Dim lB As cTestClassA = lA   ' <<<
>
> >     lB.printData()
>
> > I thought that for the <<< assignment needed to be done via a copy
> > constructor but apparently not.
>
> > Can I rely on .NET to always create a deep copy?  Am I missing
> > something?
>
> > Thanks,
> > Joe
>
> You have simply caused two variables to reference the same object.  No copy of
> the object is made.  Simply alter the data in one instance, and you will see
> that boht objects are altered.
>
> There is no concept of an automatic copy constructor in .NET.  If you want to
> create one, you can - but, it will not be automatically called.  The normal
> way to implement the concept of deep copy in .NET is to implement IClonable.
> Then clients can call the .Clone method when they want a deep copy of your
> object.
>
> --
> Tom Shelton- Hide quoted text -
>
> - Show quoted text -

Hello -

Thanks a lot for all the feedback!  I just implemented the ICloneable
and it works great.  The only problem is that since I have Option
Strict On, people will have to do a DirectCast()/CType() to cast the
result of the Clone() to the appropriate type ... but oh well ....

Thanks again,
Joe
Author
8 Jun 2009 4:26 PM
Mike
Tom Shelton wrote:

> There is no concept of an automatic copy constructor in .NET.  If you want to
> create one, you can - but, it will not be automatically called.  The normal
> way to implement the concept of deep copy in .NET is to implement IClonable.
> Then clients can call the .Clone method when they want a deep copy of your
> object.

Good note to know about IClonable. Thanks.

--
Author
8 Jun 2009 6:26 PM
Cor Ligthert[MVP]
Tom,

I once saw some code from somebody

http://www.vb-tips.com/SerializeArrayList.aspx

It is code that I have slightly changed (normally I write who stood at the
base of this code).

That I (and not me alone) always call the best way to implement a deep copy

Cor

Show quoteHide quote
"Tom Shelton" <tom_shel***@comcastXXXXXXX.net> wrote in message
news:OSHnzKF6JHA.1420@TK2MSFTNGP04.phx.gbl...
> On 2009-06-08, Joe Duchtel <duch***@gmail.com> wrote:
>> Hello -
>>
>> I always thought that if I wanted a deep copy of an object, that I
>> needed to implement a copy constructor.  However, I tried the
>> following code in VB.NET 2.0 and it worked just fine ...
>>
>> Public Class cTestClassA
>>     Protected mData As New ArrayList
>>
>>     Public Sub New(ByVal aNumber As Integer)
>>         For i As Integer = 1 To aNumber
>>             mData.Add(New cTestClassB(i.ToString))
>>         Next
>>     End Sub
>>
>>     Public Sub printData()
>>         For i As Integer = 0 To mData.Count - 1
>>             Console.WriteLine(CType(mData(i), cTestClassB).getData())
>>         Next
>>     End Sub
>> End Class
>>
>> Public Class cTestClassB
>>     Protected mName As String
>>
>>     Public Function getData() As String
>>         Return mName
>>     End Function
>>
>>     Public Sub New(ByVal aName As String)
>>         mName = aName
>>     End Sub
>> End Class
>>
>> Sub Main(ByVal aCommandArguments() As String)
>>     Dim lA As New cTestClassA(2)
>>
>>     lA.printData()
>>
>>     Dim lB As cTestClassA = lA   ' <<<
>>
>>     lB.printData()
>>
>> I thought that for the <<< assignment needed to be done via a copy
>> constructor but apparently not.
>>
>> Can I rely on .NET to always create a deep copy?  Am I missing
>> something?
>>
>> Thanks,
>> Joe
>
> You have simply caused two variables to reference the same object.  No
> copy of
> the object is made.  Simply alter the data in one instance, and you will
> see
> that boht objects are altered.
>
> There is no concept of an automatic copy constructor in .NET.  If you want
> to
> create one, you can - but, it will not be automatically called.  The
> normal
> way to implement the concept of deep copy in .NET is to implement
> IClonable.
> Then clients can call the .Clone method when they want a deep copy of your
> object.
>
>
> --
> Tom Shelton