为了账号安全,请及时绑定邮箱和手机立即绑定

什么是NullReferenceException,我该如何解决?

什么是NullReferenceException,我该如何解决?

Helenr 2019-05-20 13:46:51
我有一些代码,当它执行时,它抛出一个NullReferenceException,说:你调用的对象是空的。这是什么意思,我该怎么做才能解决这个错误?
查看完整描述

15 回答

?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

这意味着有问题的变量没有任何意义。我可以这样生成:

SqlConnection connection = null;connection.Open();

这将抛出错误,因为当我声明变量“ connection”时,它没有指向任何东西。当我尝试调用成员“ Open”时,没有引用它来解决它,它将抛出错误。

要避免此错误:

  1. 在尝试对它们执行任何操作之前始终初始化对象。

  2. 如果您不确定对象是否为null,请检查它object == null

JetBrains的Resharper工具将识别代码中可能存在空引用错误的每个位置,允许您进行空检查。这个错误是错误的头号来源,恕我直言。


查看完整回答
反对 回复 2019-05-20
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

请注意,无论情况如何,.NET中的原因始终相同:

您正在尝试使用值为Nothing/ 的引用变量null。当值为Nothingnull为引用变量时,这意味着它实际上并未持有对堆上存在的任何对象的实例的引用。

您从未向变量分配内容,从未创建分配给变量的值的实例,或者您将变量设置为Nothingnullmanual,或者您调用了将变量设置为Nothing/ 的函数null


查看完整回答
反对 回复 2019-05-20
?
繁花不似锦

TA贡献1851条经验 获得超4个赞

您正在使用包含空值引用的对象。所以它给出了一个null异常。在示例中,字符串值为null,并且在检查其长度时,发生了异常。

例:

string value = null;if (value.Length == 0) // <-- Causes exception{
    Console.WriteLine(value); // <-- Never reached}

异常错误是:

未处理的异常:

System.NullReferenceException:未将对象引用设置为对象的实例。在Program.Main()


查看完整回答
反对 回复 2019-05-20
?
动漫人物

TA贡献1815条经验 获得超10个赞

Simon Mourier举了这个例子

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

其中一个开箱转换(CAST) object(或从其中一个类System.ValueTypeSystem.Enum,或从一个接口类型)一个值类型(比其它Nullable<>本身)给出NullReferenceException

在另一个方向上,一拳击转换一个Nullable<>具有HasValue等于false 引用类型,可以给一个null参考其然后可以在以后导致NullReferenceException。经典的例子是:

DateTime? d = null;var s = d.ToString();  // OK, no exception (no boxing), returns ""var t = d.GetType();  
 // Bang! d is boxed, NullReferenceException

有时拳击以另一种方式发生。例如,使用这种非泛型扩展方法:

public static void MyExtension(this object x){
  x.ToString();}

以下代码将有问题:

DateTime? d = null;d.MyExtension();  // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.

出现这些情况是因为运行时在装箱Nullable<>实例时使用的特殊规则。


查看完整回答
反对 回复 2019-05-20
?
慕码人8056858

TA贡献1803条经验 获得超6个赞

我对回答这个问题有不同的看法。这种答案“我还能做些什么来避免它? ”

跨不同层工作时,例如在MVC应用程序中,控制器需要服务来调用业务操作。在这种情况下,可以使用Dependency Injection Container初始化服务以避免NullReferenceException。这意味着您不必担心检查null并且只需从控制器调用服务,就好像它们总是可用(并初始化)为单例或原型。

public class MyController{
    private ServiceA serviceA;
    private ServiceB serviceB;

    public MyController(ServiceA serviceA, ServiceB serviceB)
    {
        this.serviceA = serviceA;
        this.serviceB = serviceB;
    }

    public void MyMethod()
    {
        // We don't need to check null because the dependency injection container 
        // injects it, provided you took care of bootstrapping it.
        var someObject = serviceA.DoThis();
    }}


查看完整回答
反对 回复 2019-05-20
?
米脂

TA贡献1836条经验 获得超3个赞

关于“我该怎么办”,可以有很多答案。

在开发过程中防止此类错误情况的更“正式”方法是在代码中按合同设计。这意味着您需要在开发时在系统上设置类不变量,和/或甚至函数/方法前置条件后置条件

简而言之,类不变量确保您的类中存在一些在正常使用中不会被违反的约束(因此,类不会处于不一致状态)。前提条件意味着作为函数/方法的输入给出的数据必须遵循一些约束集并且永远不违反它们,并且后置条件意味着函数/方法输出必须再次遵循设置约束而不违反它们。在执行无错误程序期间永远不应违反合同条件,因此在调试模式下实际检查合同设计,同时在发布禁用合同条件,以最大化已开发的系统性能。

这样,您可以避免NullReferenceException违反约束集的情况。例如,如果X在类中使用对象属性,稍后尝试调用其中一个方法并且X具有空值,则会导致NullReferenceException

public X { get; set; }public void InvokeX(){
    X.DoSomething(); // if X value is null, you will get a NullReferenceException}

但是如果你设置“属性X必须永远不会有空值”作为方法前置条件,那么你可以阻止前面描述的场景:

//Using code contracts:[ContractInvariantMethod]protected void ObjectInvariant () {
    Contract.Invariant ( X != null );
    //...}

出于这个原因,.NET应用程序存在Code Contracts项目。

或者,可以使用断言来应用合同设计。

更新:值得一提的是,这个术语是Bertrand Meyer 在设计Eiffel编程语言时创造的。


查看完整回答
反对 回复 2019-05-20
  • 15 回答
  • 0 关注
  • 9812 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信