Create a "clone" of this object, not point to it

Let's say I got a list called

myFirstList 

And then I want to create a copy of that list so I can do some tweaks of my own. So I do this:

mySecondList = myFirstList mySecondList.doTweaks 

But I noticed that the tweaks also affect the myFirstList object! I only want the tweaks to affect the second one...

And afterwards I will want to completely delete mySecondList, so I do mySecondList = Nothing and I'm good, right?

8 Answers

Adam Rackis, I don't like your "Of course it does", because it is not at all obvious.

If you have a string variable that you assign to another string variabe, you do not change them both when making changes to one of them. They do not point to the same physical piece of memory, so why is it obvious that classes do?

Also, the thing is not even consistent. In the following case, you will have all elements in the array pointing at the same object (they all end up with the variable Number set to 10:

SourceObject = New SomeClass For i = 1 To 10 SourceObject.Number = i ObjectArray.Add = SourceObject Next i 

BUT, the following will give you 10 different instances:

For i = 1 To 10 SourceObject = New SomeClass SourceObject.Number = i ObjectArray.Add = SourceObject Next i 

Apparently the scope of the object makes a difference, so it is not at all obvious what happens.

1

Since you have not divulged the type of item that you are storing n your list, I assume it's something that's implementing IClonable (Otherwise, if you can, implement IClonable, or figure out a way to clone individual item in the list).

Try something like this

mySecondList = myFirstList.[Select](Function(i) i.Clone()).ToList() 
0

But I noticed that the tweaks also affect the myFirstList object! I only want the tweaks to affect the second one...

Of course it does. Both variables are pointing to the same object in memory. Anything you do to the one, happens to the other.

You're going to need to do either a deep clone, or a shallow one, depending on your requirements. This article should give you a better idea what you need to do

2

Expanding on Adam Rackies' answer I was able to implement the following code using VB.NET.

My goal was to copy a list of objects that served mainly as data transfer objects (i.e. database data). The first the class dtoNamedClass is defined and ShallowCopy method is added. A new variable named dtoNamedClassCloneVar is created and a LINQ select query is used to copy the object variable dtoNamedClassVar.

I was able to make changes to dtoNamedClassCloneVar without affecting dtoNamedClassVar.

Public Class dtoNamedClass ... Custom dto Property Definitions Public Function ShallowCopy() As dtoNamedClass Return DirectCast(Me.MemberwiseClone(), dtoNamedClass) End Function End Class Dim dtoNamedClassVar As List(Of dtoNamedClass) = {get your database data} Dim dtoNamedClassCloneVar = (From d In Me.dtoNamedClass Where {add clause if necessary} Select d.ShallowCopy()).ToList 
1

Here is how you do it:

'copy one object to another via reflection properties For Each p As System.Reflection.PropertyInfo In originalobject.GetType().GetProperties() If p.CanRead Then clone.GetType().GetProperty(p.Name).SetValue(clone, p.GetValue(OriginalObject, Nothing)) End If Next 

in some cases when the clone object got read-only properties you need to check that first.

For Each p As System.Reflection.PropertyInfo In originalobject.GetType().GetProperties() If p.CanRead AndAlso clone.GetType().GetProperty(p.Name).CanWrite Then clone.GetType().GetProperty(p.Name).SetValue(clone, p.GetValue(OriginalObject, Nothing)) End If Next 
2

this works for me:

mySecondList = myFirstList.ToList 

Here's an additional approach that some may prefer since System.Reflection can be slow.

You'll need to add the Newtonsoft.Json NuGet package to your solution, then:

Imports Newtonsoft.Json 

And given a class type of MyClass, cloning can be as easy as:

Dim original as New MyClass 'populate properties of original... Dim copy as New MyClass copy = JsonConvert.DeserializeObject(Of MyClass)(JsonConvert.SerializeObject(original)) 

So the approach is to first use the JSON converter to serialize the original object, and than take that serialized data and deserialize it - specifying the class type - into the class instance copy.

The JSON converters are extremely powerful and flexible; you can do all sorts of custom property mappings and manipulations if you need something the basic approach above doesn't seem to address.

1

clone is the object you are attempting to clone to.

dim clone as new YourObjectType 

You declare it like that.

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like