I have been struggling with something that I found out to be very weird. Obviously, C# behaves this way but I was wondering how to prevent it. My code is very long so I've made a small example of my dilemma:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
private List<Person> m_Persons = new List<Person>();
public Form1()
{
InitializeComponent();
Person p1 = new Person();
p1.Name = "Jack";
p1.Money = 10;
m_Persons.Add(p1);
Bank ph = new Bank();
for (int i = 0; i < 4; i++)
{
ph.Insert(p1);
Console.WriteLine(p1.Money);
}
}
}
class Person
{
public string Name { get; set; }
public int Money { get; set; }
}
class Bank
{
private List<Person> m_Customers = new List<Person>();
public void Insert(Person p_Person)
{
int index = m_Customers.FindIndex(item => item.Name == p_Person.Name);
if (index > -1)
m_Customers.ElementAt(index).Money += p_Person.Money;
else
m_Customers.Add(p_Person);
}
}
}
In the code above, my printings say:
10
20
40
80
Those values is to me right, but they should be stored in the bankclass and not in the object that are used as a reference in Insert(). Why is the p1-object getting updated?!
Person is a class, i.e. reference type. When you are inserting person to m_Customers list, you are actually creating new reference to same person instance, and adding this reference to list (list hold references to person instances). So, your program have one instance of person and six references to this instance. It does not matter which reference you will use to update person's money - your single instance will be updated at the end.

I also suggest you to read MSDN article Value and Reference Types
The p1 object is getting updated becaused Person is a reference type. This means that when you pass the object to methods, it's actually a reference TO the object which is being passed i.e. The p1 object is the exact same instance as the Person you've added to the bank. Therefore, if you update the Person in the Bank (which you do when you call the Insert method) the p1 object is also updated.
If you want to prevent this behaviour, you would have to create a new Person object within your loop. If you set the new Person object's properties to the same values each time, the Person in the bank will be updated, but not the Person object in your loop.
Alternatively you could change the Insert method so that instead of
m_Customers.Add(p_Person);
you use
m_Customers.Add(new Person{ Name = p_Person.Name, Money = p_Person.Money });
It seems you are always looping the same person:
for (int i = 0; i < 4; i++)
{
ph.Insert(p1);
Console.WriteLine(p1.Money);
}
The above code will insert p1 4 times.
In your Insert method you verify if the person already exists in the lists m_Customers, if exists, you update the money.
In your Form1 Class you need to create people of different names, if the name is the same, the money will be updated.
Try to create people inside for statement and diferent names like this:
public Form1()
{
InitializeComponent();
Bank ph = new Bank();
for (int i = 0; i < 4; i++)
{
Person p = new Person();
p.Name = "Jack" + i;
p.Money = 10;
m_Persons.Add(p);
ph.Insert(p);
Console.WriteLine(p.Money);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With