MyClass2 = MyClass1 -> ByRef????

  • Thread starter Thread starter DraguVaso
  • Start date Start date
D

DraguVaso

Hi,

I have 2 instances of a user-defined class. When I do a cls2 = cls1, and I
change a property of cls2, this property is also changed in my cls1!!

Does anybody know what the reason of this is? and how I can prevent it?

Thanks,

Pieter

I'm using VB.NET 2003.


This is my sample code:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim cls1 As New clsMyClass
Dim cls2 As clsMyClass
cls2 = Nothing
cls2 = cls1
MessageBox.Show(cls1.Icon Is Nothing)
Dim bmp As New Bitmap(20, 20, Imaging.PixelFormat.Format32bppPArgb)
cls2.Icon = bmp
MessageBox.Show(cls1.Icon Is Nothing)
End Sub



Public Class clsMyClass
Private m_Icon As Bitmap

Public Property Icon() As Bitmap
Get
Return m_Icon
End Get
Set(ByVal Value As Bitmap)
m_Icon = Value
End Set
End Property

End Class
 
Hi,
There are probably many ways to accomplish this, but one way to prevent it
would be to use a copy constructor like this: (That should do the trick)

Public Class clsMyClass
Private m_Icon As Bitmap

Public Sub New()
'Do nothing for now, but you can add your code to it
End Sub

Public Sub New(ByVal ClsToCopy as clsMyClass)
Me.Icon = ClsToCopy.Icon
End Sub

Public Property Icon() As Bitmap
Get
Return m_Icon
End Get
Set(ByVal Value As Bitmap)
m_Icon = Value
End Set
End Property

End Class
 
DraguVaso said:
I have 2 instances of a user-defined class. When I do a cls2 = cls1,
and I change a property of cls2, this property is also changed in my
cls1!!

You don't have two instances, you only have one.

Your instance is created in this line:

\\\
Dim cls1 As New clsMyClass
///

The following line does not create another instance, it simply points cls2
at the existing instance that cls1 is already referencing:

\\\
cls2 = cls1
///

After this, both cls1 and cls2 are pointing to the same object instance,
hence the behaviour you described.

To prevent it, create two object instances:

\\\
Dim cls1 As New clsMyClass
Dim cls2 As New clsMyClass
///
 
That's because cls1 and cls2 are *references* to objects and not the
actual objects themselves. Assigning cls2 to cls1 simply makes them
both refer to the same object and that's why changing a property
affects both.

I suggest you implement the ICloneable interface in your user defined
class and do something like
cls2 = (MyClass)cls1.Clone();

Regards
Senthil
 
Well, I tried that, but I have a Brush-property in my Class, and that gives
me this exception...

The type System.Drawing.Brush in Assembly System.Drawing,
Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is not
marked as serializable. at
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMember
s(RuntimeType type, Boolean excludeNonSerializable)
at
System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type
type, StreamingContext context)
etc etc etc...

Any idea to get around this problem?
 
From the exception, it looks like you tried serializing and
deserializing your class to get a copy. System.Drawing.Brush is not
serializable and that's why you are getting the exception.

Do you need to deep copy everything?

Regards
Senthil
 
Yes unfortunately yes :) It's actually a deep copy that I need to make.
I guess ThunderMusic's method will be the best now...
 
Because it doesn't work...
Dim cls1 As New clsMyClass
Dim cls2 As New clsMyClass
cls2 = cls1 '-> This still creates a reference to my cls1, so
changes I make to cls2 will be changed automaticly to cls1 also...
 
Pieter,

You are always talking about classes

Dim cls1 as New clsMyClass
Dim cls2 as New clsMyClass
is in fact
Dim obj1 as new clsMyClass
dim obj2 as new clsMyClass

Gives 2 completly independedn objects

dim obj1 = obj2

Sets the reference from obj2 to obj1, so the point to the same object

In the same time the first instanced obj2 has no reference anymore and
therefore that obj2 will be garbaged by the GC.

I hope this gives an idea,

Cor
 
I found a solution somewhere that works. It's using Reflection, and I
implemented in a New() just like ThunderMusic suggested. It works great!
Thanks a lot for the suggestions!

Imports System.Reflection

Public Sub New(ByVal clsSource As clsMyClass)
MyBase.New()

Dim pi As PropertyInfo() = GetType(clsMyClass).GetProperties
Dim objValue As Object

For intX As Integer = 0 To pi.Length - 1
With pi(intX)
'If .GetIndexParameters().Length = 0 Then
'Copy
objValue = .GetValue(clsSource, Nothing)
'Paste
.SetValue(Me, objValue, Nothing)
'Else
' Debug.WriteLine(.Name & " " & "<array>")
'End If
End With
Next intX
End Sub
 
Oh no, forget about my solution: It's totally worthless. ok, it works, but
it eats resources like hell!! It's slowing down everything, and it's too
much remarkable... :-(
 
DraguVaso said:
Because it doesn't work...
Dim cls1 As New clsMyClass
Dim cls2 As New clsMyClass
cls2 = cls1 '-> This still creates a reference to my cls1,
so changes I make to cls2 will be changed automaticly to cls1 also...

I think I'm struggling to work out what you're actually trying to do.

You asked a question about why after running the above code changes made to
cls2 also affect cls1, and we've answered that question.

What exactly is the problem you are trying to solve? Are you trying to
create two separate objects and copy all of the property values from one
object to the other?
 
Yes indeed! That's exactly what I want!
I want my cls2 to be exactly the same as my cls1, but when I change a value
in cls2, it shouldn't affect cls1. What I need is a Deep Copy...

I now made a Constructor of my clsMyclass that gets a clsMyClass argument,
and copies all it's properties one by one in its own properties. It isn't
really beautiful, but it works... My class has only 10 property's so it's
not too hard, but when having classes with much more properties a nicer
solution should be welcome, hehe :)

Thanks anyway for the explanation and the help.

Pieter
 
Pieter,

If you want a deepcopy of an object than the most simple method to make the
class from which its instanced serializable and than to serialise it and
create using deserialization a copy of that object.

I hope this helps,

Cor
 
Your solution doesn't seem to do a deep copy either. You get the
property values using reflection and just assign them to the new
object, so reference type member variables will still be shared.

Regards
Senthil
 
Yes I tried that, but unfortunately I got an error (as I mentioned alreaddy
somewhere in another post): It seems that a Brush-object in't
serializable...


The type System.Drawing.Brush in Assembly System.Drawing,
Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is not
marked as serializable. at
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMember
s(RuntimeType type, Boolean excludeNonSerializable)
at
System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type
type, StreamingContext context)
etc etc etc...
 
Back
Top