Copy Constructor needed in VB.NET 2.0?

  • Thread starter Thread starter Joe Duchtel
  • Start date Start date
J

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
 
Joe said:
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).

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
 
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
 
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
 
Joe said:
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.

---
 
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.
 
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.

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
 
Tom said:
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.

--
 
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
 
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
 
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).
 
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.


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
 
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.

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
 
Back
Top