views:

82

answers:

6

Using Nunit to test C# code with the following code block:

foreach (XmlNode node in nodeList)
{

    thisReport.Id = node.Attributes.GetNamedItem("id").Value;
    thisReport.Name = node.Attributes.GetNamedItem("name").Value;
    thisReport.Desc = node.Attributes.GetNamedItem("desc").Value;
    if (node.SelectNodes("subreport").Count > 0)
    {

        thisReport.HasSubReport = true;
        subReportNodeList = node.SelectNodes("subreport");
        foreach(XmlNode subNode in subReportNodeList)

        {

        mySubReport.ParentID = node.Attributes.GetNamedItem("id").Value;
        mySubReport.Priority = subNode.Attributes.GetNamedItem("priority").Value;
        mySubReport.SubReportId = subNode.Attributes.GetNamedItem("id").Value;
        mySubReport.SubReportName = subNode.Attributes.GetNamedItem("name").Value;
        string sTime = subNode.Attributes.GetNamedItem("time").Value;
            mySubReport.Time = Convert.ToInt16(sTime);
            thisReport.SubReportsList.Add(mySubReport);
        }
    }
    else
    {
        thisReport.HasSubReport = false;
    }
    reports.Add(thisReport);}

The code fails with a null object reference in the line: thisReport.SubreportsList.Add(mySubReport). But, looking at the locals, "thisReport" exists and has the values assigned at the top of the block, "mySubReport" exists and has the values assigned just above the line where it's added to thisReport. All the values in mySubReport are valid and SubReportsList in thisReport is a generic list of type SubReport.

So, where's the null. In other words, why does this fail? It seems so simple, it must be something really obvious that I can't see.

Appreciate any help at all.

Thanks, Randy

+1  A: 

It must be SubReportsList that is null then.

Albin Sunnanbo
+2  A: 

You should probably first do:

thisReport.SubReportsList = new List<SubReport>();
Dan Dumitru
A: 

Make sure to initialize the list by using the new keyword. Otherwise the list itself will be null.

klausbyskov
+5  A: 

You've not instantiated SubReportsList before calling Add. Do the following before adding mySubReport:

thisReport.SubReportsList = new List<SubReport>();
thisReport.SubReportsList.Add(mySubReport);

You could also change your SubReportsList property to make your life easier:

public class Report
{
    public IList<SubReport> SubReportsList
    {
        get
        {
            if (_subReportsList == null)
            {
                _subReportsList = new List<SubReport>();
            }
            return _subReportsList;
        }
    }
    private IList<SubReport> _subReportsList;
}

Doing this would instantiate your List if it's called while it's null.

GenericTypeTea
+1  A: 

SubReportsList is your null reference; you've declared it but not initialized it. You can declare a new one either in a contructor for thisReport's type, or just before you start adding things to it.

KeithS
+1  A: 

As @GenericTypeTea and @Dan Dumitru have already provided good answers I will just add that it is possible to "automatically" do this by adding an implicit construction if the value is null when you call the property. You can do this if you are not using auto-properties ala:

public class Report {
 // ... other code ...
 private List<SubReports> _subReports = null;

 public List<SubReport> SubReports {
    get {
      if (_subReports == null) { _subReports = new List<SubReports>(); }
      return _subReports;
    }
 }
}

There are some caveats to be noted, like making it thread-safe (this is off-the-cuff), but the basic implementation will work for you. I would be careful using this desing as it can cause the creation of objects you don't necessarily need just by checking properties. If that is undesirable then stick with the implementations recommended above.

GrayWizardx