2

I have some custom classes defined that include lists of other classes like so:

public class Unit
{
    public string Name { get; set; }
    public List<Group> Contains { get; set; }
}

public class Group
{
    public string Name { get; set; }
    public Type Type { get; set; }
    public int Number { get; set; }
}

public static Type basic_1 = new Type() { Name = "basic_1", Number = 1, Cost = 13 };

The basic idea is that you have a unit which contains a list of groups, each with a different type. The type contains specific properties while the classes that contain them are organizational in nature.

I then try to start building out these classes like so:

Unit unit1 = new Unit() { Name = "Unit 1" };
Group group1 = new Group() { Name = "Group 1", Number = 10, Type = basic_1 };
unit1.Contains.Add(group1);

But here I receive the error (on the Add method) "Object reference not set to an instance of an object." Looking at the locals in the debugger I can see that the Unit, Group and Type were all created successfully and the group1 contains all the Type values it's supposed to, but unit1.Contains is null.

What am I doing wrong? FYI I've never done something like this before so I don't even know if it's possible, but it seems to work fine up until this point.

3
  • 1
    Almost all cases of NullReferenceException are the same. Please see "What is a NullReferenceException in .NET?" for some hints. Commented May 1, 2014 at 20:57
  • If you don't want to change your class, just new up the list. unit1.Contains = new List<Group>(); Commented May 1, 2014 at 21:05
  • I would advise against making a writable Contains property. A list exposed as a readonly property can still be modified from outside the class (as in you can add and remove stuff in it) and this will prevent outside code to set the instance to null or to another list. Oh and don't name it Contains either. Commented May 1, 2014 at 21:24

3 Answers 3

14

Your List<Group> Contains never gets initialized, so when you try to access it, you get a null reference exception. Essentially all null reference exceptions are the same, you're trying to use an object that's null.

In this case, let's just add a default constructor to initialize the list for us.

public class Unit
{
    public string Name { get; set; }

    public List<Group> Contains { get; set; }

    public Unit()
    {
        Contains = new List<Group>();
    }
}

By the way, Contains is a terrible name for a list. Contains is usually a function call, as it's a verb. Usually better to use a noun for a collection, such as Groups.

public class Unit
{
    public string Name { get; set; }

    public List<Group> Groups { get; set; }

    public Unit()
    {
        Groups = new List<Group>();
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Ah for some reason the Contains method never occurred to me, thanks for pointing that out!
@thanby I would advise against making your list property writable, though. It's unlikely you'd want that.
@Crono On the contrary, I make them writable all the time. It just depends on the situation and how the object is intended to be used.
@mason these situations should be marginal IMHO, not your everyday use case. I can't think of a design where I'd want an object to act differently on having a null collection instead of an empty collection.
4

Your Contains list within User class never gets instantiated.

You may want to change your User class to this instead:

public class Unit
{
    public string Name { get; set; }

    List<Group> list = new List<Group>();

    public List<Group> Contains
    {
        get { return list; }
    }
}

As you can see the Contains property now only returns a list instance that can of course be modified but never reaffected. Likely, this is what you'll want.

Although this is a tad outside the scope of your question, I would suggest that you rename the Contains property to Groups instead.

3 Comments

Type or namespace name 'var' could not be found - Forgive my n00bishness but what am I missing to allow me to use that? It works fine in a method but not in the class.
You could accomplish this same thing without the need for a private field, by using a private set operator on the property. Simplifies the code. public List<Group> Contains {get; private set;}
@mason but then you'd need a constructor to instantiate the list. :)
1

You have initialized the Unit But Unit.Contains Does not initialize. Before Adding objects to Contains list it must be initialized.

Unit unit1 = new Unit() { Name = "Unit 1" };
Group group1 = new Group() { Name = "Group 1", Number = 10, Type = basic_1 };
unit1.Contains = new List<Group>();
unit1.Contains.Add(group1);

Or

In your Unit class constructor you can initialize List here the code

public class Unit
{
public string Name { get; set; }
public List<Group> Contains { get; set; }
public Unit()
{
Contains = new List<Group>();
}
}

I would prefer the 2nd solution as it will make sure that whenever Unit is initialized Contains will be initialized automatically.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.