Max Maddy
Max Maddy

Reputation: 349

Copy Reference Type from one to another C#

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

Answers (5)

InBetween
InBetween

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:

  • The instance of Test you created with new is your apartment.
  • obj is your set of keys.
  • newObj is the copy you gave the cleaning service.
  • Changing 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

Alex
Alex

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

Pushpendra
Pushpendra

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

DVK
DVK

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.

Cloning List<T>

Upvotes: 3

The_Black_Smurf
The_Black_Smurf

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

Related Questions