我有一些代码,当它执行时,它会抛出NullReferenceException,说:

对象引用未设置为对象的实例。

这意味着什么,我可以做什么来修复这个错误?


当前回答

这意味着所讨论的变量没有指向任何对象。我可以这样生成:

SqlConnection connection = null;
connection.Open();

这将引发错误,因为虽然我声明了变量“connection”,但它没有指向任何对象。当我尝试将成员称为“Open”时,没有任何引用可供它解析,它会抛出错误。

要避免此错误,请执行以下操作:

在尝试对对象执行任何操作之前,请始终初始化对象。如果您不确定对象是否为空,请使用object==null进行检查。

JetBrains的ReSharper工具将识别代码中可能出现空引用错误的每个位置,从而允许您进行空检查。这个错误是错误的头号来源,IMHO。

其他回答

抛出此异常的一个示例是:当您试图检查某个对象时,该对象为空。

例如:

string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)

if (testString.Length == 0) // Throws a nullreferenceexception
{
    //Do something
} 

当您尝试对尚未实例化的对象(即上面的代码)执行操作时,.NET运行时将抛出NullReferenceException。

与ArgumentNullException相比,ArgumentNullException通常在方法期望传递给它的内容不为null时作为防御措施抛出。

更多信息请参见C#NullReferenceException和Null参数。

另一种情况是将空对象转换为值类型。例如,下面的代码:

object o = null;
DateTime d = (DateTime)o;

它将在强制转换时引发NullReferenceException。在上面的示例中,这似乎很明显,但这可能发生在更“后期绑定”的复杂场景中,其中空对象是从您不拥有的某些代码返回的,例如,强制转换是由某些自动系统生成的。

其中一个示例是带有Calendar控件的简单ASP.NET绑定片段:

<asp:Calendar runat="server" SelectedDate="<%#Bind("Something")%>" />

这里,SelectedDate实际上是CalendarWebControl类型的DateTime类型的属性,绑定可以完全返回null。隐式ASP.NET生成器将创建一段与上述转换代码等效的代码。这将引发一个很难发现的NullReferenceException,因为它存在于ASP.NET生成的代码中,这些代码可以很好地编译。。。

这基本上是一个Null引用异常。如Microsoft所述-

尝试访问值为空的类型的成员。

这是什么意思?

这意味着,如果任何成员不具有任何价值,而我们让该成员执行某项任务,那么系统无疑会抛出一条消息,并表示-

“嘿,等等,该成员没有值,因此无法执行您正在移交的任务。”

异常本身表示正在引用某个对象,但未设置其值。因此,这表示它只在使用引用类型时发生,因为Value类型不可为null。

如果使用Value类型成员,则不会发生NullReferenceException。

class Program
{
    static void Main(string[] args)
    {
        string str = null;
        Console.WriteLine(str.Length);
        Console.ReadLine();
    }
}

上面的代码显示了分配了空值的简单字符串。

现在,当我尝试打印字符串str的长度时,我确实收到了“System.NullReferenceException”类型的未处理异常消息,因为成员str指向null,并且不能有任何长度的null。

当我们忘记实例化引用类型时,也会出现“NullReferenceException”。

假设我有一个类和成员方法。我没有实例化我的类,只是命名了我的类。现在,如果我尝试使用该方法,编译器将抛出错误或发出警告(取决于编译器)。

class Program
{
    static void Main(string[] args)
    {
        MyClass1 obj;
        obj.foo();  // Use of unassigned local variable 'obj'
    }
}

public class MyClass1
{
    internal void foo()
    {
        Console.WriteLine("Hello from foo");
    }
}

上述代码的编译器引发一个错误,即变量obj未赋值,这意味着我们的变量有空值或没有值。上述代码的编译器引发一个错误,即变量obj未赋值,这意味着我们的变量有空值或没有值。

为什么会发生这种情况?

NullReferenceException是由于我们没有检查对象的值而导致的。在代码开发中,我们经常不检查对象值。当我们忘记实例化对象时,也会出现这种情况。使用可以返回或设置空值的方法、财产、集合等也可能是此异常的原因。

如何避免?

有多种方式和方法可以避免这一著名的例外:

显式检查:我们应该坚持检查对象、财产、方法、数组和集合是否为null的传统。这可以使用if-else-if-else等条件语句简单地实现。异常处理:管理此异常的重要方法之一。使用简单的try-catch finally块,我们可以控制这个异常,并维护它的日志。这在应用程序处于生产阶段时非常有用。Null操作符:在为对象、变量、财产和字段设置值时,也可以方便地使用Null合并操作符和Null条件操作符。调试器:对于开发人员来说,我们有调试的利器。如果我们在开发过程中遇到NullReferenceException,我们可以使用调试器找到异常的源。内置方法:GetValueOrDefault()、IsNullOrWhiteSpace()和IsNullorEmpty()等系统方法检查空值,如果存在空值,则分配默认值。

这里已经有很多好的答案。你也可以在我的博客上查看更详细的描述和示例。

希望这也有帮助!

另一个可能收到此异常的一般情况是在单元测试期间模拟类。无论使用何种模拟框架,您都必须确保正确模拟类层次结构的所有适当级别。特别是,被测试代码引用的HttpContext的所有财产都必须进行模拟。

请参阅“测试自定义AuthorizationAttribute时引发的NullReferenceException”,以获取一些详细的示例。

更新C#8.02019:可为空的引用类型

C#8.0引入了可为null的引用类型和不可为null引用类型。因此,必须只检查可为null的引用类型,以避免出现NullReferenceException。


如果尚未初始化引用类型,并且希望设置或读取其财产之一,则会抛出NullReferenceException。

例子:

Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.

您可以通过检查变量是否为空来避免这种情况:

Person p = null;
if (p!=null)
{
    p.Name = "Harry"; // Not going to run to this point
}

要完全理解为什么会引发NullReferenceException,必须了解值类型和[引用类型][3]之间的区别。

因此,如果要处理值类型,则不能出现NullReferenceExceptions。尽管在处理引用类型时需要保持警惕!

正如名称所暗示的那样,只有引用类型可以保存引用或直接指向任何对象(或“null”)。而值类型始终包含值。

引用类型(必须选中这些类型):

动态对象一串

值类型(您可以忽略这些类型):

数字类型整数类型浮点类型十进制的布尔用户定义的结构