tags:

views:

136

answers:

5

What exactly happens when adding an object to a collection such as List?

List<Person> people = new List<Person>();
Person dan = new Person() { Name="daniel", Age=10 };
people.Add(dan);
dan = new Person() { Name = "hw", Age = 44 };

When I execute the above code, the List<Person> peopledoes not get affected by final line. So I am assuming that the list copies the references of the added object, so when change the reference, the list does not get affected. am I correct?

+4  A: 

Well, the code you've shown doesn't actually add anything to the list at all. I assume you meant to have:

people.Add(dan);

in there somewhere?

But yes, the List<T> contains references to objects. It doesn't know about where the references have come from. It's worth being clear about the difference between a variable and its value. When you call:

people.Add(dan);

that copies the value of the argument expression (dan) in this case as the initial value of the parameter within List<T>.Add. That value is just a reference - it has no association with the dan variable, other than it happened to be the value of the variable at the time when List<T>.Add was called.

It's exactly the same as the following situation:

Person p1 = new Person { Name = "Jon" };
p2 = p1;
p1 = new Person { Name = "Dan" };

Here, the value of p2 will still be a reference to the person with the name "Jon" - the second line just copies the value of p1 to p2 rather than associating the two variables together. Once you understand this, you can apply the same logic to method arguments.

Jon Skeet
+3  A: 

Well with that code the List<Person> people should not get affected by the 2nd line either.

Anyway, the List<Person> gets a reference if you use .Add() so if you modify that person later, the person in the list is "modified" too (it's the same person), but if you assign the person to someone else you're not affecting the reference, you're assigning the symbol to a new reference.

e.g.:

List<Person> people = new List<Person>(); 
Person dan = new Person() { Name="daniel", Age=10 }; 
people.Add(dan);

/* DanData = { Name="daniel", Age=10 }; 
 * `people[0]` maps to "DanData"
 * `dan` maps to "DanData" */

dan.Name = "daniel the first";
string dansNameInList = people[0].Name; /* equals "daniel the first" */

/* DanData = { Name="daniel the first", Age=10 }; 
 * `people[0]` maps to "DanData"
 * `dan` maps to "DanData" */

people[0].Name = "daniel again";
string dansName = dan.Name /* equals "daniel again" */

/* DanData = { Name="daniel again", Age=10 }; 
 * `people[0]` maps to "DanData"
 * `dan` maps to "DanData" */

dan = new Person() { Name = "hw", Age = 44 }; 
string dansNameInListAfterChange = people[0].Name /* equals "daniel again" */
string dansNameAfterChange = dan.Name /* equals "hw" */

/* DanData = { Name="daniel again", Age=10 }; 
 * NewData = { Name = "hw", Age = 44 }; 
 * `people[0]` maps to "DanData"
 * `dan` maps to "NewData" */
Graphain
+1  A: 

To answer the original question, assuming you intended to add the person to the list before calling the third line:

Yes, the list only stores a reference to the object. In C#, ALL object variables are references.

So when you call new Person() a second time, the reference held by your variable dan is updated to point to the new instance. If the first instance has no reference pointed to it, it will be garbage collected in the next round. If you had added the first instance to the list, the list would still retain it's reference to the first instance.

Dr Herbie
A: 

Adding at the end of your code

people[0] = dan;

would point to your new dan object.

SiN
A: 

It's important in .NET programming to have a good understanding of the difference between reference types and value types. This article provides a good overview: http://www.albahari.com/valuevsreftypes.aspx

In this case, you created two Person objects (Daniel, age 10, and hw, age 44). It's the variables that reference the two objects that created the confusion.


Person dan = new Person() { Name="daniel", Age=10 };

Here, a local variable, dan, is assigned a reference to the newly created (Daniel, age 10) object.


people.Add(dan);

Here, the property people[0] is (indirectly via the List.Add method) assigned a reference to the existing (Daniel, age 10) object.


dan = new Person() { Name = "hw", Age = 44 };

Here, the local variable, dan, is assigned a reference to the newly created (hw, age 44) object. But the property people[0] still holds a reference to the existing (Daniel, age 10) object.

C. Dragon 76