1

So I'm beginning to learn about object oriented programming and I'm having some trouble understanding the relationship between all these elements.

I'm building a simple text game with RPG style fights.

For this I have several classes, including one for :

Weapons :

class Weapon
{
    private string _name;
    private int _mindamage;
    private int _maxdamage;

    public string Name { get { return _name; } set { _name = value; } }
    public int MaxDamage { get { return _maxdamage; } set { _maxdamage = value; } }
    public int MinDamage { get { return _mindamage; } set { _mindamage = value; } }

    public Weapon(int mindamage, int maxdamage, string name)
    {
        this._name = name;
        this._mindamage = mindamage;
        this._maxdamage = maxdamage;
    }
}

Characters :

class Character
{
    private string _name;
    private int _life;
    private Weapon _weapon;

    public string Name { get { return _name; } set { _name = value; } }
    public int Life { get { return _life; } set { _life = value; } }
    public Weapon Weapon { get { return _weapon; } set { _weapon = value; } }

    public Character(string name, Weapon weapon)
    {
        _name = name;
        _weapon = weapon;
        _life = 100;
    }

And the one that I'm struggling with : It's a class that represents a group of characters in a list :

class Company
{

    private int _size;
    private List<Character> _members;

    public int Size { get { return _size; } set { _size = value; } }
    public List<Character> Members { get { return _members; } set { _members = value; } }

    public Company(string[] names, Weapon[] weapons)
    {
        int length = names.Length;
        List<Character> _members = new List<Character>();
        for (int i = 0; i < length; i++)
        {
            _members.Add(new Character(names[i], weapons[i]));
            Console.WriteLine("added {0} to character list", _members[i].Name);
        }
        Console.WriteLine("characters {0} and {1} exist after the for", _members[0].Name, _members[1].Name);
        _size = length;
    }

}

This code compiles perfectly fine but when it executes it throws me an error in my Program.cs class if I try to access a Character's Name inside my list, for example :

static void Main(string[] args)
    {
        Weapon anduril = new Weapon(55, 80, "Anduril");
        Weapon hache = new Weapon(25, 60, "hache");
        Weapon lame = new Weapon(30, 50, "lame");
        Weapon arc = new Weapon(30, 40, "arc");
        string[] gentils = { "Aragorn", "Legolas", "Gimli" };
        string[] méchants = { "Lurtz", "Berserk", "UrukA" };
        Weapon[] armes = { anduril, arc, hache };
        Weapon[] armes2 = { lame, lame, arc };
        Company Communauté = new Company(gentils, armes);
        Company Uruks = new Company(méchants, armes2);
        Console.WriteLine(Communauté.Members[0].Name);

The last line throws me a null object error. As you can see I put some Console.WriteLine calls in my Company constructor to be sure that the constructor was actually adding Character to a List, and it works. So were is the problem ?

Is it something with the way I wrote the getter/setter for Members ?

  • 1
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Bill Tür stands with Ukraine Jun 04 '16 at 13:11
  • 2
    A couple of side-notes: I'd personally try to stick to ASCII names for identifiers - and follow .NET naming conventions (so make your local variable names start with a lower case letter, for example). I'd also suggest learning about automatically-implemented properties - they'll make your code much simpler. – Jon Skeet Jun 04 '16 at 13:14
  • Its not even close to be the same question.... – Dr.Haimovitz Jun 04 '16 at 13:15
  • I know but I can't find which part would'nt be initialized in this case :( – Antoine Martin Jun 04 '16 at 13:16
  • 2
    You have two different things both called _members. You're confusing them. – Eric Lippert Jun 04 '16 at 13:18

4 Answers4

11
List<Character> _members = new List<Character>();

That declares a new local called _members, but what you intended to do was initialize the field _members. The field is never initialized, and so when you access its members, null reference exception.

So don't do that. It should be

this._members = new List<Character>();

Or even better, initialize it in the declaration.

But the real takeaway here is: today would be a good day to learn to use a debugger. You have certain assumptions about what the program does. Those assumptions are wrong. By watching the program in the debugger and verifying at each step whether your assumptions are valid, you will quickly find the bug. Staring at the code for an hour, giving up, and asking Stack Overflow is a really bad debugging technique compared with running the code in a debugger. Printing out the state of the program is a good first step, but it is much better to actually watch the program run.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Don't know why you were downvoted, but thanks, I guess I still have a lot to learn about this. I will definitely look at the debugger next time, I admit I hadn't thought about it. – Antoine Martin Jun 04 '16 at 13:27
3

Instead of filling _members class variable you are initiating a different variable called _members by declaring a new list.

try this instead:

public Company(string[] names, Weapon[] weapons)
{
    int length = names.Length;
    _members = new List<Character>();
    for (int i = 0; i < length; i++)
    {
        _members.Add(new Character(names[i], weapons[i]));
        Console.WriteLine("added {0} to character list", _members[i].Name);
    }
    Console.WriteLine("characters {0} and {1} exist after the for", _members[0].Name, _members[1].Name);
    _size = length;
}
Dr.Haimovitz
  • 1,568
  • 12
  • 16
2

As say Eric Lippert - this is problem with scope variable _members. But you can use local variable in your function - just before end copy to class member:

this._members =_members;

And better rename local variable to differente name :)

Aleksandr Zolotov
  • 1,078
  • 3
  • 19
  • 32
1

In your Company constructor, you're declaring a new variable called _members which shadows the class level _members.

If you remove the List from before the _members in the constructor, it will use the correct one and should work.

ryan.rousseau
  • 1,595
  • 1
  • 11
  • 22