C# 中的 NullReferenceException:如何查找并修复此错误

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

什么是 NullReferenceException 以及如何应对?C# 开发者完整指南

\n\n

您是否曾见过这条可怕的消息:“Object reference not set to an instance of an object”?如果您使用 C# 编程至少一周,那么您很可能遇到过。这就是 NullReferenceException —— .NET 世界中最常见的错误。它吓唬新手,但有经验的开发者知道:这只是程序在说“我不知道该操作什么,给我一个对象”。

\n\n

在本文中,我们将探讨 NullReferenceException 产生的原因、如何找到它,以及最重要的是,如何预防它。您将学会编写更安全的代码,并减少调试时间。

\n\n

用简单的话说,什么是 NullReferenceException?

\n\n

想象一下,您订了一份披萨,但外卖员空手而来。您问:“我的披萨呢?”,他回答:“我不知道,我什么都没有。” NullReferenceException 的工作原理大致如此。您试图调用一个方法或访问一个值为 null 的变量的属性。编译器不会发现这一点,但在运行时程序会崩溃。

\n\n

在 C# 中,任何引用类型变量(类、接口、字符串、数组)都可能是 null。如果您尝试对此类变量执行操作,就会引发异常。

\n\n

NullReferenceException 最常见的发生场景

\n\n

让我们看一些导致此错误的真实代码示例。

\n\n

1. 未初始化的变量

\n
string name;\nConsole.WriteLine(name.Length); // NullReferenceException
\n

变量 name 已声明但未初始化。默认情况下,它等于 null。

\n\n

2. 方法返回 null

\n
public string GetUserName(int id)\n{\n    // 如果未找到用户,返回 null\n    return null;\n}\n\nvar user = GetUserName(42);\nConsole.WriteLine(user.ToUpper()); // NullReferenceException
\n\n

3. 访问集合中不存在的元素

\n
var list = new List<string> { "A", "B" };\nvar item = list[5]; // ArgumentOutOfRangeException,但如果元素是 null...\n// 这是 Dictionary 的示例:\nvar dict = new Dictionary<int, string>();\nvar value = dict[1]; // KeyNotFoundException,但如果键存在而值为 null 呢?
\n\n

4. 调用链

\n
class Address { public string City { get; set; } }\nclass Person { public Address Address { get; set; } }\n\nvar person = new Person();\nConsole.WriteLine(person.Address.City); // NullReferenceException,因为 Address == null
\n\n

如何找到 NullReferenceException:初学者调试指南

\n\n

当程序崩溃时,Visual Studio 或 Rider 会显示调用堆栈。其中会指出发生错误的行。但问题往往更深层。以下是查找步骤:

\n\n
    \n
  • 查看错误所在的行。那里使用了哪个变量?它肯定不是 null 吗?
  • \n
  • 检查值的来源。如果它是某个方法的结果——查看该方法是否可能返回 null。
  • \n
  • 使用断点。在错误行之前设置断点,并检查所有变量的值。
  • \n
  • 添加条件断点。在 Visual Studio 中,您可以设置带条件的断点:myVar == null。
  • \n
\n\n

如何修复 NullReferenceException:5 种经过验证的方法

\n\n

好消息是:NullReferenceException 几乎总是可以预防的。以下是您可以采取的措施。

\n\n

1. null 检查(老派的 if 语句)

\n
if (name != null)\n{\n    Console.WriteLine(name.Length);\n}\nelse\n{\n    Console.WriteLine("未设置名称");\n}
\n

这很有效,但如果检查过多,会使代码变得冗长

博客

书籍推荐