开发者

Null Object Reference

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)
        {
      开发者_JAVA百科      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 on the line:

            thisReport.SubreportsList.Add(mySubReport)

But looking at the locals, thisReport exists and has the values assigned at the top of the block, and 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? It seems so simple, it must be something really obvious that I can't see.


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.


You should probably first do:

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


It must be SubReportsList that is null then.


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.


thisReport.SubReportsList is your null reference; you've declared it but not initialized it. You can initialize it (probably with a new instance) either in a constructor for thisReport's type, or just before you start adding things to it.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜