Reputation: 43
Basically the purpose of my code is as follows: I have a collection of agents, with "Matricule" and "Temps Base". Some agents have only one "Temps Base", and they will be only once in the collection, but others have more than one "Temps Base", and therefore will appear several times. If an agent has only one "Temps Base" (represented by a double), no problem. If he has more than one, for example three, I just want to add them up, keeping only one object but which contains the sum of the three doubles.
Here is my class:
public class AgentJournalier
{
public string Matricule { get; set; }
public double TempsBase{ get; set; }
}
My collections :
private ObservableCollection<AgentModel> _TousAgents;
public ObservableCollection<AgentModel> TousAgents
{
get
{
return _TousAgents;
}
set
{
if (value != _TousAgents)
{
_TousAgents = value;
RaisePropertyChanged(nameof(TousAgents));
}
}
}
private ObservableCollection<AgentModel> _AgentsContratEnCours;
public ObservableCollection<AgentModel> AgentsContratEnCours
{
get
{
return _AgentsContratEnCours;
}
set
{
if (value != _AgentsContratEnCours)
{
_AgentsContratEnCours = value;
RaisePropertyChanged(nameof(AgentsContratEnCours));
}
}
}
For this test, my Collection TousAgents will contain 3 rows :
Matricule : Bec - TempsBase : 100
Matricule : Bec - TempsBase : -25
Matricule : Bec - TempsBase : -10
My code :
foreach (AgentModel tsag in TousAgents)
{
if (AgentsContratEnCours.Any(p => p.Matricule == tsag.Matricule) == false)
{
AgentsContratEnCours.Add(tsag);
}
else
{
AgentModel AgentDejaDansLaListe = new AgentModel();
AgentDejaDansLaListe = AgentsContratEnCours.Where(x => x.Matricule == tsag.Matricule).FirstOrDefault();
AgentsContratEnCours.Remove(AgentsContratEnCours.Where(x => x.Matricule == tsag.Matricule).FirstOrDefault());
AgentDejaDansLaListe.TempsBase = AgentDejaDansLaListe.TempsBase + tsag.TempsBase;
AgentsContratEnCours.Add(AgentDejaDansLaListe);
}
}
foreach (AgentModel tsag in TousAgents)
{
Console.WriteLine($"Temps base : {tsag.TempsBase}");
}
foreach (AgentModel tsag in AgentsContratEnCours)
{
Console.WriteLine($"Temps base total : {tsag.TempsBase}");
}
Considering an agent who would be three times in the list with the same "Matricule" but with 3 different "TempsBase" (ex : 100, -10, -25), the output I would like is the following:
Output :
Temps base : 100
Temps base : -25
Temps base : -10
Temps base total : 65
But the output I actually have is this one:
Output :
Temps base : 65 <== Why ??
Temps base : -25
Temps base : -10
Temps base total : 65
Obviously, if I call the method a second time, "Temps Base" continues to decrement (because it no longer has its original value, 100, but the new one: 65):
Output :
Temps base : 30 <== Why ??
Temps base : -25
Temps base : -10
Temps base total : 30
I would like to understand why this first value in "TousAgents" changes. My goal is that the values in the first Collection never change, so I create a second one : AgentsContratEnCours. But when I change the value in AgentsContratEnCours, it also changes it in TousAgents even if I don't assign anything manually to "TousAgents". Can you explain me why ? And how can I avoid this?
Upvotes: 2
Views: 41
Reputation: 17085
The problematic assumption that you made regarding reference types led you to this mistake. The false assumption is in the following code, can you spot it?
AgentModel AgentDejaDansLaListe = new AgentModel();
AgentDejaDansLaListe = AgentsContratEnCours.Where(x => x.Matricule == tsag.Matricule).FirstOrDefault();
AgentDejaDansLaListe.TempsBase = AgentDejaDansLaListe.TempsBase + tsag.TempsBase;
Let me explain. AgentModel
is a reference type it means if you change its properties (Marticule and TempsBase) in an AgentModel
they will change in all copies of it.
In the first line you create a new AgentModel
named AgentDejaDansLaListe
then on the second line you throw it away (into the garbage collector) then assign a completely different reference to it.
In the last line you modify the TempsBase of that object which also changes the TempsBase of that original object in the list, because AgentModel
is a reference type.
To fix this, either use a struct for AgentModel
or implement Clone in it.
Upvotes: 4