【问题标题】:Checking for Null in Constructor在构造函数中检查 Null
【发布时间】:2011-01-25 15:57:36
【问题描述】:

我真的想找出易于调试的可重用代码的最佳实践。我在开发人员中遇到了一种我还不太了解的常见做法。

public MyConstructor(Object myObject)
{
    if (myObject == null)
        throw new ArgumentNullException("myObject is null.");
    _myObject = myObject;
}

似乎几乎没有必要进行这项检查。但我认为这是因为我不完全了解进行此检查的好处是什么。似乎无论如何都会抛出空引用异常?我可能错了,真的很想听听一些想法。

谢谢。

【问题讨论】:

  • 您所做的不是必需的,您可以在引用该对象之前检查以确保它不为空。当然,在初始化对象时验证您将使用的内容是一种非常有效的方法。
  • @Ramhound - 这是使用 DI 框架(例如 StructureMap)时的常用方法,您不必直接控制传入构造函数的内容。如果你的类没有myObject 是无用的,并且这是唯一初始化它的地方,那么尽早抛出异常是有意义的,这样你就知道它们了。在一个长时间运行的网络应用程序中,你可能不知道这个问题,直到有人碰巧调用了一个需要该对象的方法。

标签: c# exception-handling null


【解决方案1】:

对于编译器,null 是一个合法的构造函数参数。

您的类可能能够处理myObject 的空值。但如果它不能——如果你的类在myObject 为空时会中断——那么检查构造函数允许你fail fast

【讨论】:

  • 解释得很好。我特别喜欢“快速失败”这个词。感谢您的见解。
【解决方案2】:

在许多情况下,传递null 对象是完全合法的——对于这个类,实现者希望确保你不能创建一个没有传递有效Object 实例的类的实例,所以必须有以后不要检查 - 尽早确保这一点是一个好习惯,这将在构造函数中。

【讨论】:

    【解决方案3】:

    如果您低于 4.0,您可以执行以下操作:

     public ctor(IEnjection ninjaWeapon) 
     {
         Contract.Requires<ArgumentNullException>(ninjaWeapon != null);
         this.deadlyWeaponary.Add(ninjaWeapon);
     }
    

    如果您使用的是旧版本,请参考 Microsoft.Contract 来做同样的事情。

    【讨论】:

    • 但是如果代码契约没有在编译后的步骤中被重写,那么代码契约将什么也做不了。
    【解决方案4】:

    编译器不知道对象的值,所以你必须在运行时检查它以确保它不会被空值调用。

    这也取决于您的特定解决方案。你不需要抛出异常,我只会在你不能让该值为 null 的情况下抛出它,如果它为 null,那是一个例外情况。

    【讨论】:

      【解决方案5】:

      我认为一般无法判断是否需要检查 null。这取决于您是否可以使用空值变量。 Null 本身并不是一个糟糕的状态。您可能会遇到允许变量为空而不允许变量为空的情况。

      问问自己允许空值是否有意义,并相应地设计构造函数。

      【讨论】:

        【解决方案6】:

        您可以实现一个简单的ThrowIfNull 扩展方法来减少您每次编写的代码。 Jon Skeet 在他的 blog 和引用的 SO 文章 here 中对此进行了介绍。

        【讨论】:

        【解决方案7】:

        其他人已经正确指出,null 参数的传递可能有效也可能无效,具体取决于使用代码的功能。

        如果不希望使用 null 参数,则可以从 C# 7.0 开始使用 throw 表达式,它允许我们更简洁地重写 null 检查代码,如下例所示:

        public MyConstructor(Object myObject)
        {
            _myObject = myObject ?? throw new ArgumentNullException(nameof(myObject));
        }
        

        上面会将_myObject的值设置为参数myObject除非该参数是null,在这种情况下会抛出ArgumentNullException

        【讨论】:

          【解决方案8】:

          您需要显式检查 null,因为编译器不知道,还因为 null 可以是有效参数。

          【讨论】:

            【解决方案9】:

            好处是在对象构造的时候会抛出异常,所以你可以很容易地追踪到哪部分代码是罪魁祸首。如果您的代码需要非空的myobject 值并且您没有在构造函数中对其进行验证,那么当您使用myObject_ 时将抛出NullReferenceException,您将不得不手动回溯以查看是谁发送了该空值在。

            【讨论】:

              猜你喜欢
              • 2017-11-24
              • 2014-12-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-09-24
              • 2011-08-30
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多