4

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!

4

3 回答 3

4

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;
}
于 2013-08-23T10:17:19.227 回答
0
  1. You don't need to pass list as ref, if you not intend to set army to another list
  2. Did you forget to add infantry to list? List army = new List(); Infantry infantry = new Infantry(); Marine marine = new Marine(); army.Add(Marine);
于 2013-08-23T10:17:16.993 回答
0

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

于 2013-08-23T10:47:13.397 回答