James
James

Reputation: 2600

What's the different between clone method and assign the instance to another directly

I want to know, if I have a class named Test, what's the difference below

Test test = new Test();
Test newTest = test;
Test newTest2 = test.Clone();

What's the different between newTest and newTest2? Anyone can help? Thanks in advance!

Upvotes: 3

Views: 2580

Answers (5)

supercat
supercat

Reputation: 81227

To understand the distinction, one must first understand what an object reference is. Since the term "reference" is used to refer to a number of different concepts, I like the term "Object ID". To use an automotive analogy, an object ID is a slip of paper with a car's VIN on it. If you hand the paint shop a piece of paper with "VIN ZX357" written on it and ask the shop to paint it blue, the shop won't paint the slip of paper blue, but rather they will find the car with that VIN number and paint that car blue.

If one has a variable Wuzzle of type Car (which is reference type) that happens to hold "VIN ZX357", and another variable Fuzzle, and one says Fuzzle = Wuzzle, then Fuzzle will--like Wuzzle hold "VIN ZX357". There will still be one car. One will just have two slips of paper, both of which hold the same VIN, and thus refer to the same car. A statement like Wuzzle.Color=Purple will cause the car whose VIN is ZX357to be painted purple. A request to examine Fuzzle.Color will look at car ZX357and report that it's purple.

If instead of saying Fuzzle = Wuzzle, one had said Fuzzle = (Car)(Wuzzle.Clone()), the effect would be to create a new car that was just like VIN ZX357, except that it would have a different VIN number (e.g. QL793) and Fuzzle would hold the new VIN, not 3941QXY5). Saying Wuzzle.Color = Orange would then paint car 3941QXY5 orange, but it wouldn't affect car QL793.

Variables of interface type are treated just like any other reference type. One could substitute IColorizable for Car and the behavior would be exactly the same.

It's important to note that ICloneable isn't a very good interface; a much better interface is ICloneable<T> which returns an object of type T. There are two big advantages to this interface:

  1. With ICloneable, it's necessary to typecast the return type to the type of object one wants. This is a bit ugly. ICloneable<T> eliminates this requirement.
  2. With ICloneable, there can be some ambiguity as to which object references within an object should be copied as-is to the clone, and which ones should themselves be cloned. The ambiguity isn't nearly as bad as some people make it out to be, but the generic ICloneable<T> can make it a little clearer. For example, if one has an object CloneableSortedList<T>, then calling ICloneable<CloneableSortedList<T>.Clone() on that list should return a new CloneableSortedList which contains the same references to type T as the original one did. By contrast, if one has a CloneableSortedUserList, calling ICloneable<CloneableSortedUserList> should return a new CloneableSortedUserList which will regard the users' attributes, rather than the user object references, as values (thus copying them if they are mutable).

Upvotes: 2

kol
kol

Reputation: 28708

Assignment copies only the reference, not the object itself.

If your class implements IClonable.Clone, it can be written to perform a deep copy operation, that is, to return a newly allocated object of the same type, the fields of which are copies of the original. It's an interesting question what to do when a field is a reference type: copy the reference, or deep-copy the referenced object? For example, Object.MemberwiseClone copies only the reference (this is called a shallow copy), but if you choose to implement IClonable.Clone, then you can decide this yourself.

Upvotes: 1

UnhandledExcepSean
UnhandledExcepSean

Reputation: 12804

New test actually points to the same object in memory as test, so modifying newTest changes test. newTest2 is actually a copy of test.

Upvotes: 0

Reed Copsey
Reed Copsey

Reputation: 564641

When you assign the instance, if Test is a class, you're actually copying the reference, but test and newTest will both point to the same instance in memory.

This means that both variables point to the same object:

Test test = new Test();
test.Foo = 24;
Test newTest = test;
newTest.Foo = 42;
Console.WriteLine(test.Foo); // Prints 42!

Clone(), on the other hand, typically is used to indicate a copy of the object itself, which means that test and newTest2 would point to different objects, so the above wouldn't happen.

Note that, if test is a struct (value type), then a direct assignment is effectively a full (shallow) copy of the object, by value.

Upvotes: 2

BrokenGlass
BrokenGlass

Reputation: 160952

Test newTest = test;

Since Test is a reference type (class), newTest now references the same object as test. If you change the object test references, that will be reflected in newTest since they both reference to the same object.

Test newTest2 = test.Clone();

Assuming Clone() is returning a new instance and does a deep copy (it truly depends on your implementation) , newTest2 is referring to a completely separate object, any changes in test won't affect it.

Upvotes: 0

Related Questions