Ref on a list not changing values
I'm moving over from Java to C#, and been coding some example programs. Now I have come across a List of different objects (IUnit) and when I make a call to a certain value in the list to change it's value, it changes all the values. I have added a reference to the List - As per other Stack overflow questions.
So I have the following classes
interface IUnit { int HealthPoints { set; get; } String ArmyType { get; } }
This is the base class I call to create a list of Army Types (Marines/Infantry). The implementation is the same expect a change to the values inside the class.
public class Infantry : IUnit { private int health = 100; protected String armyType = "Infantry"; public int HealthPoints { get { return health; } set { health = value; } } public String ArmyType { get { return armyType; } }
I then initialize the List with the following code
List<IUnit> army = new List<IUnit>(); Infantry infantry = new Infantry(); Marine marine = new Marine(); army.Add(Marine);
Then I have a method, which just takes away 25 from the health points.
public void ShotRandomGuy(ref List<IUnit> army) { army[0].HealthPoints = army[0].HealthPoints - 25; }
I then call that method as shown below.
battle.ShotRandomGuy(ref army);
However it takes the 25 away from all the Objects in that List. How would I stop it doing that? I have added a reference to the List, so I would of thought it would of taken it away from the the original List. Do I need to clone the list? Would that work?
Or is it more of a design issue?
Thank you!
Answers
Looks like you are adding same instance of unit many times to list. Thus all list items point to single object in memory. Modifying any item modifies that object.
List<IUnit> army = new List<IUnit>(); Infantry infantry = new Infantry(); for(int i = 0; i < 10; i++) { // adds same instance each time army.Add(infantry); }
You should instantiate new unit when adding units to list. E.g.
List<IUnit> army = new List<IUnit>(); for(int i = 0; i < 10; i++) { // create new instance each time Infantry infantry = new Infantry(); army.Add(infantry); }
BTW you don't need ref here:
public void ShotRandomGuy(List<IUnit> army) { Random r = new Random(); var unit = army[r.Next(army.Count)]; unit.HealthPoints -= 25; }
- You don't need to pass list as ref, if you not intend to set army to another list
- Did you forget to add infantry to list? List army = new List(); Infantry infantry = new Infantry(); Marine marine = new Marine(); army.Add(Marine);
You could keep infantry and marine in lists, and sort through them with for.
Something like this would work for instantiating the list.
breadCollection = new List<InteractiveObject>(); for(int i = 0; i < totaltObjects; i++) breadCollection.ElementAt(i).Add(new InteractiveObject());
Whenever you have to access the contents of the list to make changes do something like this.
int shotUnit?; shotUnit = unitNumber if(shot != null) { breadCollection.ElementAt(i).Remove(alive) breadCollection.ElementAt(i).Add(dead) shotUnit = null; }
I believe this would work for your issue. You could also write something for changing numerical values of properties with the