Reputation: 349
Below is my class
public Class Test
{
int id {get;set;}
string name {get;set;}
}
I am creating an object of this class and assigning values.
var obj = new Test();
obj.id = 1;
obj.name = "test";
var newobj = obj;
newobj.name ="NewTest";
Below is the output
Console.WriteLine(obj.name); //NewTest
Console.WriteLine(newobj.name); //NewTest
Why value of obj is changing when i change value of a property present in new obj. I know its very solution, I am not sure why I am not able to find. I don't want value of obj to get changed if i changed value in newobj.
Upvotes: 1
Views: 4710
Reputation: 32780
You buy a new apartment. You get a set of keys that give you access to that apartment. You hire someone to clean up your apartment and you give him a copy of your set keys so that he can get inside. When you get home from work late at night, your apartment is clean! How come?
This dumb analogy is exactly whats happening in your code:
Test
you created with new
is your apartment.obj
is your set of keys.newObj
is the copy you gave the cleaning service.Name
is cleaning up your apartment (modify the object in some way).The important thing to clearly understand here is that the value of obj
or newObj
is not the instance of Test
. The value stored in the variable is the memory address where the object lives.
Same as a key gives you access to your apartment, variables obj
and newObj
give you access to the object they are pointing at. When you copy the variable obj
to newObj
you are simply copying the means to access the object (memory address), not the object itself.
Things are radically diferent with value types, but thats another story.
Upvotes: 0
Reputation: 8116
You are not creating a copy, you are merely assigning the reference of an object (obj
) to another variable (newobj
). Accessing either of them points to the same location in memory.
To create a copy of an object, you have to clone it. See https://stackoverflow.com/a/78612/1028323 https://stackoverflow.com/a/129395/1028323 for example.
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
Upvotes: 5
Reputation: 1712
var newobj = obj;
This is causing the reference of obj to get assigned to newobj. There really isn't a difference in the memory location where they point to with the above statement. If you want to have a obj with same values but remain unaffected when values of newobj change you should do it this way.
var obj = new Test();
obj.id = 1;
obj.name = "test";
var newobj = new Test();
newobj.id = obj.id;
newobj.name = obj.name;
newobj.name ="NewTest";
Upvotes: 0
Reputation: 2792
As mentioned in the comments, both obj and newObj are pointing to the same underlying in-memory object, which is why changing something on one also changes something on the other. This is because they are reference types (as opposed to value types). If you want two different objects, you have a couple of options. The first is to create a new object and manually assign the properties:
var test1 = new Test() { id = 1, name = "Foo }
var test2 = new Test() { id = test1.id, name = test1.name }
The second option is to clone the object. While there are many ways of doing this (reflection, serialization, expression trees, third party libraries), I've found that using serialization is the simplest way to perform cloning provided that you aren't intending on doing it thousands of times per second. See the answer below for information on using the BinaryFormatter to clone objects.
Upvotes: 3
Reputation: 5269
newobj
ain't creating a new instance... it's just another pointer to the same instance you created with var obj = new Test();
Upvotes: 2