Reputation: 2600
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
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:
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.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
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
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
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
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