【问题标题】:NullReferenceException when accessing some object访问某些对象时出现 NullReferenceException
【发布时间】:2014-04-23 14:50:27
【问题描述】:

我知道这是一个菜鸟错误,但当我访问已设置的对象时,我真的不知道为什么会出现此错误。

xlocyloc 都是局部变量。

gameBorder.FormInstance.tableLayoutPanel1.GetControlFromPosition(xloc, yloc).BackgroundImage = Properties.Resources.Image;

然而,这是在表单类中设置的:

namespace csharp_build
{
    public partial class gameBorder : Form
    {
        public static gameBorder FormInstance;

        public gameBorder()
        {
            FormInstance = this; 
            InitializeComponent();            
        }
    }
}

知道为什么会这样吗?会不会是因为表单类被引用为gameBorder,这就是构造函数的调用,而解决方案资源管理器中表单类的名称是Form1.cs?
我知道这是一个菜鸟问题,我道歉,但任何帮助将不胜感激。

【问题讨论】:

  • xlocyloc 设置在哪里?
  • 我敢打赌 GetControlFromPosition 将返回 null。尝试将其拆分为:var temp = gameBorder.FormInstance.tableLayoutPanel1.GetControlFromPosition(xloc, yloc) 并检查 temp 的值
  • 如果在请求的坐标处没有控制会发生什么?它返回 NULL,您尝试读取 NULL 的 BackgroundImage。 What is a NullReferenceException?
  • 将间接链接在一起隐藏了空值。调试中的第 1 步是检查每个步骤:FormInstance 是否为空?是tableLayoutPanelGetControlFromPosition() 会返回任何东西吗? Properties.Resource.Image 是非空的吗?使用 IDE 的调试工具。

标签: c# .net winforms nullreferenceexception


【解决方案1】:

如果您确定tableLayoutPanel1 存在且不为空,则将您的代码更改为此,看看会发生什么:

  var control = gameBorder.FormInstance.tableLayoutPanel1.GetControlFromPosition
      (xloc, yloc);
  if (control == null) throw new NullReferenceException(
           "No control at those coordinates");
  control.BackgroundImage = Properties.Resources.Image;

天哪,伙计们,这是用于分析、调试的代码,以帮助找出问题的原因,仅此而已.....

警告 警告 警告:不打算作为最终生产代码
感谢下面的@SriramSakthivel cmets,请注意这里抛出NullReferenceException 仅用于调试/分析目的,绝不应在生产版本中由应用程序代码抛出。

【讨论】:

  • NullReferenceException 是一个保留的例外。永远不要从用户代码中抛出。
  • @Siriam,不要学究,这是为了说明/揭示/分析问题,你听说过“调试”这个概念吗??
  • 出于调试目的,Debug.Assert 在这里更合适。
  • @SriramSakthivel,感谢源代码。 :D
  • @CharlesBretana 你的插图可以是正确的异常类型,不是吗?谁知道这是为了说明?可能会误导未来的访问者。
【解决方案2】:

链接成员和方法结果的方式使您很难一目了然地确定导致NullReferenceException 被抛出的原因。 FormInstance 可能是 null,如果在创建任何 gameBorder 实例之前访问它。尽管不太可能,tableLayoutPanel 也可能是 null。如果指定单元格上没有控件,GetControlFromPosition 方法的结果很可能也是。

当您在此类代码中遇到此类问题时,最好的做法是分解调用链。这样您就可以快速判断问题出在哪里。

你也可以发code assertions,像这样:

var formInstance = gameBorder.FormInstance;
Debug.Assert(formInstance != null);
var controlAtPos = formInstance.tableLayoutPanel1.GetControlFromPosition(xloc, yloc);
Debug.Assert(controlAtPos != null);

controlAtPos.BackgroundImage = Properties.Resources.Image; // You may want to make some assertions on resolving your image instance too

代码断言的美妙之处在于很容易将它们排除在编译到生产代码中。默认情况下,它在调试配置中编译并在发布配置中排除。通过这种方式,您可以从它提供的调试帮助中受益,而不必担心部署代码中的额外开销。

请记住这一点,如果您将来再次遇到此问题,它将很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    • 2021-08-25
    • 1970-01-01
    相关资源
    最近更新 更多