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