空对象引用

发布于 2024-09-19 22:27:36 字数 1523 浏览 5 评论 0原文

使用 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);
}

代码失败,行上出现空对象引用:

            thisReport.SubreportsList.Add(mySubReport)

但查看局部变量, thisReport 存在,并且在块的顶部分配了值,并且 mySubReport 存在,并且在其添加到此Report 的行上方分配了值。 mySubReport 中的所有值均有效,并且 thisReport 中的 SubReportsListSubReport 类型的通用列表。

那么,空值在哪里呢?看起来很简单,一定是一些很明显但我看不到的东西。

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 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

假面具 2024-09-26 22:27:36

在调用 Add 之前您尚未实例化 SubReportsList。在添加 mySubReport 之前执行以下操作:

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

您还可以更改 SubReportsList 属性以使您的生活更轻松:

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

如果在 List 为 null 时调用它,则执行此操作会实例化您的 List。

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.

许仙没带伞 2024-09-26 22:27:36

你可能首先应该这样做:

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

You should probably first do:

thisReport.SubReportsList = new List<SubReport>();
阿楠 2024-09-26 22:27:36

那么它一定是 SubReportsList 为 null。

It must be SubReportsList that is null then.

梦冥 2024-09-26 22:27:36

由于 @GenericTypeTea 和 @Dan Dumitru 已经提供了很好的答案,我将补充一点,如果在调用属性时值为 null,则可以通过添加隐式构造来“自动”执行此操作。如果您不使用自动属性,则可以执行此操作:

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

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

有一些注意事项需要注意,例如使其成为线程安全的(这是即兴的),但基本实现将适合您。我会小心使用这种设计,因为它可能会导致仅通过检查属性就创建不一定需要的对象。如果这是不可取的,那么请坚持上面推荐的实现。

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.

×眷恋的温暖 2024-09-26 22:27:36

thisReport.SubReportsList 是您的空引用;你已经声明了它但没有初始化它。您可以在 thisReport 类型的构造函数中初始化它(可能使用新实例),或者在开始向其中添加内容之前初始化它。

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.

浅听莫相离 2024-09-26 22:27:36

确保使用 new 关键字初始化列表。否则列表本身将为空。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文