473,405 Members | 2,310 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Deep copy ArrayList problem.

I need to perform a Deep Copy on an ArrayList.

I wrote a small sample app to prove this could be done:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");
b = (ArrayList) a.Clone();

a[0] = "World";

This appears to work fine. However, when I try it in my application,
both ArrayLists point to the same memory.

Each element in my ArrayList is a custom class I have written, so I am
wondering would this have any impact on the call to Clone() ?

At a high level, what I need to do is create a very large structure once
on startup (the ArrayList will be static) and when each request comes in
from a client, I take a deep copy of the structure and allow each client
their own working copy. This would cut down a massive amoutn of
processing on my part.

Can anyone help?

Steven

*** Sent via Developersdex http://www.developersdex.com ***
Nov 20 '06 #1
22 15889
daa
try:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");
b = a;
Steven Blair wrote:
I need to perform a Deep Copy on an ArrayList.

I wrote a small sample app to prove this could be done:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");
b = (ArrayList) a.Clone();

a[0] = "World";

This appears to work fine. However, when I try it in my application,
both ArrayLists point to the same memory.

Each element in my ArrayList is a custom class I have written, so I am
wondering would this have any impact on the call to Clone() ?

At a high level, what I need to do is create a very large structure once
on startup (the ArrayList will be static) and when each request comes in
from a client, I take a deep copy of the structure and allow each client
their own working copy. This would cut down a massive amoutn of
processing on my part.

Can anyone help?

Steven

*** Sent via Developersdex http://www.developersdex.com ***
Nov 20 '06 #2
Steven Blair wrote:
I need to perform a Deep Copy on an ArrayList.

I wrote a small sample app to prove this could be done:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");
b = (ArrayList) a.Clone();

a[0] = "World";

This appears to work fine. However, when I try it in my application,
both ArrayLists point to the same memory.
I think you can use the ArrayList.CopyTo along with AddRange method:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");

string[a.Count] strings;
a.CopyTo(strings);

b.AddRange(strings);

Check the syntax, but I think this may work.

Nov 20 '06 #3
Steven Blair <st**********@btinternet.comwrote:
I need to perform a Deep Copy on an ArrayList.

I wrote a small sample app to prove this could be done:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");
b = (ArrayList) a.Clone();

a[0] = "World";

This appears to work fine. However, when I try it in my application,
both ArrayLists point to the same memory.
Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
Each element in my ArrayList is a custom class I have written, so I am
wondering would this have any impact on the call to Clone() ?
Well, each list will refer to the same set of objects to start with,
although the lists themselves are independent. If you want the objects
themselves to be cloned (as your subject line suggests) you'll need to
call Clone() on each of the objects, eg:

for (int i=0; i < copiedList.Count; i++)
{
copiedList[i] = copiedList[i].Clone();
}

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 20 '06 #4
daa <mi********@gmail.comwrote:
try:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");
b = a;
That ends up with a single list, with two variables referring to the
same list. In fact, assigning a new ArrayList reference to b to start
with is pointless.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 20 '06 #5
Thanks for the replies.

Here is an example which closely matches the problem:

static void Main(string[] args)
{
ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add( new ExampleClass("Hello") );
b = (ArrayList) a.Clone(); //I expected this to clone the whole
structure.

((ExampleClass)a[0]).m_Value = "World"; //This changes b[0] as well!
}

public class ExampleClass
{
public string m_Value;

public ExampleClass(string s)
{
m_Value = s;
}

public override string ToString()
{
return m_Value;
}
}

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #6
Jon,

Since each class is custom, I can only call Clone on the ArrayList
itself:

a.Clone();

and not

a[i].Clone();
*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #7
Steven Blair wrote:
I need to perform a Deep Copy on an ArrayList.

I wrote a small sample app to prove this could be done:

ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

a.Add("Hello");
b = (ArrayList) a.Clone();

a[0] = "World";

This appears to work fine. However, when I try it in my application,
both ArrayLists point to the same memory.

Each element in my ArrayList is a custom class I have written, so I am
wondering would this have any impact on the call to Clone() ?

At a high level, what I need to do is create a very large structure
once on startup (the ArrayList will be static) and when each request
comes in from a client, I take a deep copy of the structure and allow
each client their own working copy. This would cut down a massive
amoutn of processing on my part.

Can anyone help?
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, a);
stream.Seek(0, SeekOrigin.Begin);
ArrayList b = (ArrayList)formatter.Deserialize(stream);
stream.Close();
stream.Dispose();

This gives you perfectly deep copies of a complete object graph.

(disclaimer: written from my bare head so it might have some small
syntax errors here and there)

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Nov 21 '06 #8
Frans,

Thanks for the reply.

Is this code a hit on performance?

I need to determine if creating a deep copy is more expensive than
actually building the structure from scratch each time.

My original structure has seem times of >50ms to construct!

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #9
Steven Blair wrote:
Thanks for the reply.

Is this code a hit on performance?
Yes, that will be a hit on performance.
I need to determine if creating a deep copy is more expensive than
actually building the structure from scratch each time.

My original structure has seem times of >50ms to construct!
A much better idea than serialization *if* you're in control of all the
objects is to implement your own Clone method, and invoke it on each of
the objects in the list.

Jon

Nov 21 '06 #10
Ok, using the example above, here is what I think the finished code
looks like:

static void Main(string[] args)
{
ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

ExampleClass t = new ExampleClass("Hello");

a.Add( t );

//At this point, I would loop round the count of the ArrayList
b.Add( ((ExampleClass)a[0]).Clone() );

((ExampleClass)a[0]).m_Value = "World";
}

public class ExampleClass : ICloneable
{
public string m_Value;

public ExampleClass(string s)
{
m_Value = s;
}

public override string ToString()
{
return m_Value;
}

object ICloneable.Clone()
{
return this.Clone();
}

public virtual ExampleClass Clone()
{
return this.MemberwiseClone() as ExampleClass;
}
}

Any final comments?

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #11

Steven Blair wrote:
Ok, using the example above, here is what I think the finished code
looks like:

static void Main(string[] args)
{
ArrayList a = new ArrayList();
ArrayList b = new ArrayList();

ExampleClass t = new ExampleClass("Hello");

a.Add( t );

//At this point, I would loop round the count of the ArrayList
b.Add( ((ExampleClass)a[0]).Clone() );

((ExampleClass)a[0]).m_Value = "World";
}
Yup, that would be fine - except you could just use a foreach on the
loop, rather than using Count explictly.

Of course, MemberwiseClone only gives a shallow copy too - you'll need
to clone in an appropriate way for each class. Note that casting to
ICloneable instead of ExampleClass would be more flexible.

Jon

Nov 21 '06 #12
Now I am confused.
My testing appears to show a deep copy is taking place, so how can the
MemberwiseClone only give me a shallow copy?

This line of code:

((ExampleClass)a[0]).m_Value = "World";

Changes object a, but b is unchanged.

Good point regarding the casting. I have now updated that.

I double check the code, and I do appear to have 2 seperate classes
after using the Clone().

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #13
Because it clones the fields essentially as a memcopy operation. For
value-type fields (numerics etc) this is fine. However, for reference-types
(custom classes, or lists, collections, arrays etc) you will simply clone
the *pointer* to the actual class on the heap, so to get a true "deep" clone
you would have to keep going. Note that for immutable reference types (such
as string) you won't really notice the difference.

It is unfortunate that IClonable doesn't distinguish between shallow and
deep.

Marc

Nov 21 '06 #14
oh, now I understand:

public class ExampleClass : ICloneable
{
public string m_Value;
public ArrayList m_Names; // :( shallow copy time

public ExampleClass(string s)
{
m_Value = s;
m_Names = new ArrayList();
}

public override string ToString()
{
return m_Value;
}

object ICloneable.Clone()
{
return this.Clone();
}

public virtual ICloneable Clone()
{
return this.MemberwiseClone() as ICloneable;
}
}

m_Names would be a shallow copy :(

This is realy not good. It seems extremely complicated to copy (deep)
structures in C#.

I think living with the slow structure construction time is the only
option for me at the moment.

Thanks for the help everyone.

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #15
Is this how I would deep copy an ArrayList inside my custom class:

public class ExampleClass : ICloneable
{
public string m_Value;
public ArrayList m_Names;

public ExampleClass(string s)
{
m_Value = s;
m_Names = new ArrayList();
}

public override string ToString()
{
return m_Value;
}

object ICloneable.Clone()
{
return this.Clone();
}

public virtual ICloneable Clone()
{
ExampleClass x = this.MemberwiseClone() as ExampleClass;

//This is how I would Clone reference type?
x.m_Names = this.m_Names.Clone() as ArrayList;

return x as ICloneable;
}
}

This does seem to work, but would like to double check.

My custom class in the production software is mainly made up of string,
int, bool and enum. A few methods and an ArrayList. As far as I can see,
the ArrayList is the only object that would be a shallow copy?

Hopefully this is case closed this time!

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #16
"Steven Blair" <st**********@btinternet.comwrote in message
news:Oy**************@TK2MSFTNGP02.phx.gbl...
This does seem to work, but would like to double check.
Try:
public class ExampleClass : ICloneable
{
public string m_Value;
public ArrayList m_Names;

public ExampleClass(string s, ArrayList a)
{
m_Value = s;
m_Names = a;
}

public ExampleClass() { }

public override string ToString()
{
return m_Value;
}

object ICloneable.Clone()
{
return this.Clone();
}

public virtual ExampleClass Clone()
{
ExampleClass result = new ExampleClass();
if (m_Names != null)
{
result.m_Names = new ArrayList();
foreach (object o in m_Names)
{
result.m_Names.Add(o); //again, if o are reference types you'll have to
make your own clone
}
}

return result;
}
}

Cheers!

Chris.
Nov 21 '06 #17
Chris,

o is reference type.

I assumed the code I had in there would do the deep copy now?

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #18
"Steven Blair" <st**********@btinternet.comwrote in message
news:OW**************@TK2MSFTNGP06.phx.gbl...
Chris,

o is reference type.

I assumed the code I had in there would do the deep copy now?
Both reference types and value types derive from object.

ArrayList.Clone() produces a shallow copy. If you want a deep copy you'll
have to create another instance (memory reference) and copy the members
across, cloning the reference types as necessary.

Don't forget that shallow copy means referring to the same instance, whereas
a deep copy is a difference instance.
e.g.

ExampleClass one = new ExampleClass;
ExampleClass two = one;

both two and one refer to the same instance ("shallow").

ExampleClass one = new ExampleClass;
ExampleClass two = new ExampleClass;

one and two are different instances ("deep").

Cheers!

Chris.
Nov 21 '06 #19
"Christopher Ireland" <ci******@gmail.comwrote in message
news:u7**************@TK2MSFTNGP06.phx.gbl...
"Steven Blair" <st**********@btinternet.comwrote in message
news:OW**************@TK2MSFTNGP06.phx.gbl...
>Chris,

o is reference type.

I assumed the code I had in there would do the deep copy now?

Both reference types and value types derive from object.

ArrayList.Clone() produces a shallow copy. If you want a deep copy you'll
have to create another instance (memory reference) and copy the members
across, cloning the reference types as necessary.
You might find this article helpful in understanding what's going on:
http://www.c-sharpcorner.com/UploadF...rp_memory.aspx

Cheers!

Chris.
Nov 21 '06 #20
Steven.. To be clear Clone on a string simply returns a new reference to
the same string.

http://msdn.microsoft.com/library/de.../en-us/dnguine
t/html/drguinet5_update.asp

When is Clone not Clone?
But what if you want to have two separate strings, each containing the
same value? Well, generally you do not want this. Why waste the memory?
And because strings are immutable, there's not much point in having two
separate strings that have the same value.

So, although String implements IClonable, String.Clone simply returns a
reference to the same string without cloning it.

All is not lost, however: You can use the static method Copy if you
insist on having a second copy of the string.
Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Nov 21 '06 #21
Yup, I understand this. But my lasy query is to do with this line:

x.m_Names = this.m_Names.Clone() as ArrayList;

m_Names is an ArrayList and I am looking for confirmation that the last
class I posted would be a compleye deep copy?

I think I have everything covered now (one string and one ArrayList).

*** Sent via Developersdex http://www.developersdex.com ***
Nov 22 '06 #22
Steven Blair wrote:
Frans,

Thanks for the reply.

Is this code a hit on performance?
depends on the graph. It takes performance of course, however it also
works no matter what graph you have. It can be an option if you have to
work with object instances of classes you don't control.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Nov 22 '06 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Marc Lefebvre | last post by:
there is an easy way to make a deep copy of an arraylist ? suppose I have an arraylist of COptions implements ICloneable I have need to overload the Clone() methode of a derived ArrayList...
1
by: Marc Lefebvre | last post by:
there is an easy way to make a deep copy of an arraylist ? suppose I have an arraylist of COptions implements ICloneable I have need to overload the Clone() methode of a derived ArrayList...
4
by: fperfect13 | last post by:
Hi, I wanted to perform a deep copy of an array. Searching on google I ran into different opinions : C# Interview Questions (http://blogs.wwwcoder.com/tsvmadhav/archive/2005/04/08/2882.aspx)...
1
by: Marc Lefebvre | last post by:
there is an easy way to make a deep copy of an arraylist ? suppose I have an arraylist of COptions implements ICloneable I have need to overload the Clone() methode of a derived ArrayList...
6
by: Desmond Cassidy | last post by:
Hi, I'm sure this has been asked several times before but I'll risk it ;-) If I wish to save an Arraylist to another Arraylist and work on te original without affecting the contents of the new...
8
by: Esmail Bonakdarian | last post by:
Hello, I am relatively new to C# but like it. I have run into a problem to which I haven't been able to find a solution despite looking. I have an ArrayList that contains several...
2
by: Lubomir | last post by:
Hi, I would like to ask if the constructor ArrayList(ICollection c) performs the deep or shallow copy of "c" collection. If it perfoms just shallow copy, is there any method for doing a deep...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.