Reputation: 45
MemberwiseClone()
will create shallow copy, which will do a bit-by-bit copy of a value type and only copy the references of a reference type. We would need to create a deep copy to have an independent copy of a reference type. This is ok. I get this.
Now my question is: why does a System.Object
variable react differently when MemberwiseClone() is called?
Eg:
Public class Test
{
public int x;
public object obj;
public Test MyClone()
{
return (Test) this.MemberwiseClone();
}
}
Now access this in my Main method:
public static void Main()
{
Test obj1 = new obj1;
obj1.x = 1;
obj1.obj = "x";
Test obj2 = obj1.MyClone();
obj2.obj = "y"
}
Should this not change the value of obj1.obj
to y? Since obj is an instance of System.Object
which is obviously a reference type. But it does not change - obj1.obj
gives x and obj2.obj
gives y. Why is this?
Upvotes: 1
Views: 2518
Reputation: 2867
your code contains 3 syntax errors (this cannot run)
considering your code:
public static void Main() { Test obj1 = new obj1; obj1.x = 1; obj1.obj = "x";
Test obj2 = obj1.MyClone();
obj2.obj = "y"
}
your wrong thinking lies here:
obj2.obj = "y"
this does not change the value of obj, it assings a different string object which is not related to the non-cloned instance.
this is because every string is an immutable object. a different string results in a different object on the heap.
But if you actually manage to change the string content itself, then you get the expected effect.
using unsafe mode you can prove it this way:
using System.Diagnostics;
static class Program
{
static void Main()
{
Test obj1 = new Test();
obj1.x = 1;
obj1.obj = "abc";
Test obj2 = obj1.MyClone();
var obj1Str = obj1.obj as string;
ReverseString(obj1Str);
var obj2Str = obj2.obj as string;
Debug.Print(obj2Str); // "cba"
}
static unsafe void ReverseString(string str)
{
int i = 0;
int j = str.Length - 1;
fixed (char* fstr = str)
while (i < j)
{
char temp = fstr[j];
fstr[j--] = fstr[i];
fstr[i++] = temp;
}
}
}
public class Test
{
public int x;
public object obj;
public Test MyClone()
{
return (Test)MemberwiseClone();
}
}
Upvotes: 1
Reputation: 9214
It's because you don't change state of field obj
. You assign it.
public static void Main()
{
Test obj1 = new obj1;
obj1.x = 1;
obj1.obj = new List<string> {"x"};
Test obj2 = obj1.MyClone();
((List<string>) obj2.obj).Add("y"); //now it contains {x, y} in obj1 and obj2
}
Upvotes: 2