469,962 Members | 2,347 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,962 developers. It's quick & easy.

Copy Reference Type?

Ok, this should be simple, but how do I copy a reference type by value?

Meaning

SomeComplexObject s1 = new SomeComplexObject ();
SomeComplexObject s2 = new SomeComplexObject ();
s1.color = "red";
s2 = s1;
s2.color = "blue";

I want to copy s1 to s2 and have them point to different points in memory,
so that if I change s2.color I won't change s1.color... How do I do that?
The actual object has like 30-ish parameters so I'm hoping I don't have to
assign each one separately!

Aug 15 '06 #1
15 15677
Brett,

There is no standard way to do this. The framework defines an IClonable
interface which is used for things like this. However, it doesn't say
whether or not you should do a deep copy or a shallow copy of the object.

The simplest way to do this would be to implement IClonable, and then
have it return what MemberwiseClone (a protected method on Object) returns.
However, this is only one layer deep. If you have object references in your
object which is being copied, then those objects are not copied, but rather,
their references.

If you want a dirty way to do this, and the object is marked as
serializable, then you can serialize the object to a memory stream, and then
deserialize it back, and you have a deep copy.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Ok, this should be simple, but how do I copy a reference type by value?

Meaning

SomeComplexObject s1 = new SomeComplexObject ();
SomeComplexObject s2 = new SomeComplexObject ();
s1.color = "red";
s2 = s1;
s2.color = "blue";

I want to copy s1 to s2 and have them point to different points in memory,
so that if I change s2.color I won't change s1.color... How do I do that?
The actual object has like 30-ish parameters so I'm hoping I don't have to
assign each one separately!

Aug 15 '06 #2
You can write your own Copy or Clone method to do this, but that's what
you'll have to do.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

Orange you bland I stopped splaying bananas?
"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Ok, this should be simple, but how do I copy a reference type by value?

Meaning

SomeComplexObject s1 = new SomeComplexObject ();
SomeComplexObject s2 = new SomeComplexObject ();
s1.color = "red";
s2 = s1;
s2.color = "blue";

I want to copy s1 to s2 and have them point to different points in memory,
so that if I change s2.color I won't change s1.color... How do I do that?
The actual object has like 30-ish parameters so I'm hoping I don't have to
assign each one separately!

Aug 15 '06 #3
"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Ok, this should be simple, but how do I copy a reference type by value?

Meaning

SomeComplexObject s1 = new SomeComplexObject ();
SomeComplexObject s2 = new SomeComplexObject ();
s1.color = "red";
s2 = s1;
s2.color = "blue";

I want to copy s1 to s2 and have them point to different points in memory,
so that if I change s2.color I won't change s1.color... How do I do that?
The actual object has like 30-ish parameters so I'm hoping I don't have to
assign each one separately!
Yes, you have to write a copy method returning new instance of your class
manually. You can make a shallow copy usign the MemberwiseClone() method
(inherited from object) but the fields of the new instance will still
reference the same objects in memory.

A possible hack to perform a deep copy is to serialize and deserialize the
instance.
Aug 15 '06 #4
"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Ok, this should be simple, but how do I copy a reference type by value?
I religiously implement IClonable in all my classes where possible, along
with a copy constructor. The consumer of the class can then use Clone or
the copy constructor, as desired.

-- Alan
Aug 15 '06 #5
Thanks everyone for the answers... Just a question about the copy
contructor, it seems like that could cause a bug --- meaning that if I add a
new property to my class and forget to include it in the copy contructor,
that one property being referenced instead of copied probably wouldn't show
up for quite a while... do you have a good methodology that mitigates that
risk (other than not being forgetful :) )?
"Alan Pretre" <no@spamwrote in message
news:eF**************@TK2MSFTNGP02.phx.gbl...
"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>Ok, this should be simple, but how do I copy a reference type by value?

I religiously implement IClonable in all my classes where possible, along
with a copy constructor. The consumer of the class can then use Clone or
the copy constructor, as desired.

-- Alan


Aug 15 '06 #6
Brett,

You might want to implement a Reflection-based property to do this.
Basically, cycle through the fields on a class, digging into sub classes,
etc, etc, setting the values.

And I have say that I think that Alan's solution is not a good general
purpose solution. Implementing copy constructors (which really don't have
any special significance in C# unlike the way they did in C++) and IClonable
on all of your classes might not give you the best solution (you have to
ask, why are you doing this?).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Brett Wickard" <no****@nospam.comwrote in message
news:O5****************@TK2MSFTNGP02.phx.gbl...
Thanks everyone for the answers... Just a question about the copy
contructor, it seems like that could cause a bug --- meaning that if I add
a new property to my class and forget to include it in the copy
contructor, that one property being referenced instead of copied probably
wouldn't show up for quite a while... do you have a good methodology that
mitigates that risk (other than not being forgetful :) )?
"Alan Pretre" <no@spamwrote in message
news:eF**************@TK2MSFTNGP02.phx.gbl...
>"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>>Ok, this should be simple, but how do I copy a reference type by value?

I religiously implement IClonable in all my classes where possible, along
with a copy constructor. The consumer of the class can then use Clone or
the copy constructor, as desired.

-- Alan



Aug 15 '06 #7
"Brett Wickard" <no****@nospam.comwrote in message
news:O5****************@TK2MSFTNGP02.phx.gbl...
Thanks everyone for the answers... Just a question about the copy
contructor, it seems like that could cause a bug --- meaning that if I add
a new property to my class and forget to include it in the copy
contructor, that one property being referenced instead of copied probably
wouldn't show up for quite a while... do you have a good methodology that
mitigates that risk (other than not being forgetful :) )?
Right you are about a potential for bugs...

Since the copy constructor is implemented using ICloneable.Clone(), the
issue is implementing Clone(). Couple things. If your object is flat, then
you can implement Clone using MemberwiseClone(). If you have a nested
object, and it is serializable, then there is an in-memory deepcopy routine
you can use to copy it. Google the net or the C# newsgroup to find them,
they are around. Nicholas also mentions reflection.

The final step of course, is to write unit tests of your clone routine. You
do do unit testing, right?

-- Alan
Aug 15 '06 #8
Interesting stuff to digest --- thanks again for taking the time to respond!

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote in
message news:ul****************@TK2MSFTNGP04.phx.gbl...
Brett,

You might want to implement a Reflection-based property to do this.
Basically, cycle through the fields on a class, digging into sub classes,
etc, etc, setting the values.

And I have say that I think that Alan's solution is not a good general
purpose solution. Implementing copy constructors (which really don't have
any special significance in C# unlike the way they did in C++) and
IClonable on all of your classes might not give you the best solution (you
have to ask, why are you doing this?).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Brett Wickard" <no****@nospam.comwrote in message
news:O5****************@TK2MSFTNGP02.phx.gbl...
>Thanks everyone for the answers... Just a question about the copy
contructor, it seems like that could cause a bug --- meaning that if I
add a new property to my class and forget to include it in the copy
contructor, that one property being referenced instead of copied probably
wouldn't show up for quite a while... do you have a good methodology that
mitigates that risk (other than not being forgetful :) )?
"Alan Pretre" <no@spamwrote in message
news:eF**************@TK2MSFTNGP02.phx.gbl...
>>"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl.. .
Ok, this should be simple, but how do I copy a reference type by value?

I religiously implement IClonable in all my classes where possible,
along with a copy constructor. The consumer of the class can then use
Clone or the copy constructor, as desired.

-- Alan




Aug 15 '06 #9
Thanks for the response. Since I have no idea what unit testing is, I have
some reading to do!

"Alan Pretre" <no@spamwrote in message
news:u1**************@TK2MSFTNGP06.phx.gbl...
"Brett Wickard" <no****@nospam.comwrote in message
news:O5****************@TK2MSFTNGP02.phx.gbl...
>Thanks everyone for the answers... Just a question about the copy
contructor, it seems like that could cause a bug --- meaning that if I
add a new property to my class and forget to include it in the copy
contructor, that one property being referenced instead of copied probably
wouldn't show up for quite a while... do you have a good methodology that
mitigates that risk (other than not being forgetful :) )?

Right you are about a potential for bugs...

Since the copy constructor is implemented using ICloneable.Clone(), the
issue is implementing Clone(). Couple things. If your object is flat,
then you can implement Clone using MemberwiseClone(). If you have a
nested object, and it is serializable, then there is an in-memory deepcopy
routine you can use to copy it. Google the net or the C# newsgroup to
find them, they are around. Nicholas also mentions reflection.

The final step of course, is to write unit tests of your clone routine.
You do do unit testing, right?

-- Alan


Aug 15 '06 #10
"Brett Wickard" <no****@nospam.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Thanks for the response.
I mangled my description in my last post, let me give an example of
Clone/Copy constructor.

namespace MyNamespace {
public class A : System.ICloneable {
private int _i, _j;

// Default constructor.
public A() {
_i = _j = 0;
return;
}

// Copy constructor.
public A(A A) {
_i = A._i;
_j = A._j;
return;
}

object System.ICloneable.Clone() {
return new A(this);
}
}

public class B : System.ICloneable {
private A _A;
private int _i;

// Default constructor.
public B() {
_i = 0;
return;
}

// Copy constructor. Deep copy.
public B(B B) {
_A = new A(B._A); // Uses copy constructor, this is the deep
copy.
_i = B._i;
return;
}

object System.ICloneable.Clone() {
return new B(this);
}
}
}

Since I have no idea what unit testing is, I have some reading to do!
See http://nunit.org/
-- Alan
Aug 15 '06 #11
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote in
message news:ul****************@TK2MSFTNGP04.phx.gbl...
Implementing copy constructors (which really don't have any special
significance in C# unlike the way they did in C++)
Using a copy constructor allows me to write as in (i):

Assuming,
A Obj1, Obj2;
Obj1 = new A();

Then,
Obj2 = new A(Obj1); // (i)

Or,
Obj2 = Obj1.Clone() As A // (ii)

Or,
Obj2 = (A) Obj1.Clone(); // (iii)
You can argue about which is better. But the point is there is next to no
cost in the class to implement Clone() if you already have a copy
constructor.

-- Alan
Aug 15 '06 #12
It's a valid point, but you are ignoring two important questions:

a) How deep is too deep?

and

b) What is the pratical application of having a copy constructor on
everything, as well as an implementation of IClonable.

There is not one standard answer for either of these, and the questions
are very closely intertwined. It's something the OP has to answer for
himself, depending on the semantics that he wants in his program.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Alan Pretre" <no@spamwrote in message
news:Ol*************@TK2MSFTNGP05.phx.gbl...
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote
in message news:ul****************@TK2MSFTNGP04.phx.gbl...
>Implementing copy constructors (which really don't have any special
significance in C# unlike the way they did in C++)

Using a copy constructor allows me to write as in (i):

Assuming,
A Obj1, Obj2;
Obj1 = new A();

Then,
Obj2 = new A(Obj1); // (i)

Or,
Obj2 = Obj1.Clone() As A // (ii)

Or,
Obj2 = (A) Obj1.Clone(); // (iii)
You can argue about which is better. But the point is there is next to no
cost in the class to implement Clone() if you already have a copy
constructor.

-- Alan


Aug 15 '06 #13
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote in
message news:Of**************@TK2MSFTNGP03.phx.gbl...
a) How deep is too deep?
In answer to the question, "how do I make a deep copy of an object?", then
disciplined use of copy constructors and/or ICloneable works. Of course,
there is always the "You (client) may think you want this, but you really
don't" issue that the class designer needs to consider.
b) What is the pratical application of having a copy constructor on
everything, as well as an implementation of IClonable.
This is a discipline that I always follow for my own classes. It gets
tricky when you need to implement a clone on a class that wraps another one
that provides no equivalent, like some framework classes, but in almost all
cases it is doable, if it makes sense to copy the object at all.

>Using a copy constructor allows me to write as in (i):

Assuming,
A Obj1, Obj2;
Obj1 = new A();

Then,
Obj2 = new A(Obj1); // (i)

Or,
Obj2 = Obj1.Clone() As A // (ii)

Or,
Obj2 = (A) Obj1.Clone(); // (iii)
As an aside, what I posted earlier doesn't compile. After posting I
realized that C# requires casting to ICloneable:

Obj2 = ((System.ICloneable) Obj1).Clone() As A // (ii)
or
Obj2 = (A) ((System.ICloneable) Obj1).Clone(); // (iii)

which makes

Obj2 = new A(Obj1); // (i)

look even better.

-- Alan
Aug 15 '06 #14
As an aside, what I posted earlier doesn't compile. After posting I
realized that C# requires casting to ICloneable:

Obj2 = ((System.ICloneable) Obj1).Clone() As A // (ii)
or
Obj2 = (A) ((System.ICloneable) Obj1).Clone(); // (iii)

which makes

Obj2 = new A(Obj1); // (i)

look even better.

-- Alan
Just a side note: the cast is required only if the interface is implemented
explicitly.
Aug 15 '06 #15
"Lebesgue" <le******@gmail.comwrote in message
news:u3**************@TK2MSFTNGP05.phx.gbl...
Just a side note: the cast is required only if the interface is
implemented explicitly.
Thanks. To be honest, I rarely, if ever, use Clone() directly since I have
the copy constructors. Again, it is up to the preference of the consumer.

-- Alan
Aug 15 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

42 posts views Thread by Edward Diener | last post: by
11 posts views Thread by Sam Wilson [Bentley] | last post: by
14 posts views Thread by MSR | last post: by
5 posts views Thread by Tony Johansson | last post: by
1 post views Thread by | last post: by
5 posts views Thread by lion | last post: by
6 posts views Thread by kjm424 | last post: by
1 post views Thread by rainxy | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.