简体   繁体   English

空对象引用

[英]Null Object Reference

Using Nunit to test C# code with the following code block: 使用Nunit使用以下代码块测试C#代码:

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 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. 但是看一下本地, thisReport存在并且在块的顶部分配了值,并且mySubReport存在并且在将它添加到thisReport的行的上方分配了值。 All the values in mySubReport are valid and SubReportsList in thisReport is a generic list of type SubReport . 在所有值mySubReport是有效的, SubReportsListthisReport是类型的泛型列表SubReport

So, where's the null? 那么,null在哪里? It seems so simple, it must be something really obvious that I can't see. 看起来很简单,它一定是我看不到的非常明显的东西。

You've not instantiated SubReportsList before calling Add . 在调用Add之前,您没有实例化SubReportsList。 Do the following before adding mySubReport : 在添加mySubReport之前执行以下mySubReport

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

You could also change your SubReportsList property to make your life easier: 您还可以更改SubReportsList属性以使您的生活更轻松:

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. 执行此操作将实例化List,如果它在null时被调用。

你应该先做:

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

它必须是SubReportsList ,然后为null。

thisReport.SubReportsList is your null reference; thisReport.SubReportsList是你的空引用; 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. 您可以在thisReport类型的构造函数中初始化它(可能使用新实例),或者在开始向其添加内容之前初始化它。

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. 由于@GenericTypeTea和@Dan Dumitru已经提供了很好的答案,我将补充说,如果在调用属性时值为null,则可以通过添加隐式构造来“自动”执行此操作。 You can do this if you are not using auto-properties ala: 如果您不使用自动属性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. 如果这是不合需要的,那么坚持上面推荐的实现。

Make sure to initialize the list by using the new keyword. 确保使用new关键字初始化列表。 Otherwise the list itself will be null. 否则列表本身将为null。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM