C# 检查构造函数中的Null

C# 检查构造函数中的Null,c#,exception-handling,null,C#,Exception Handling,Null,我真的在试图找出易于调试的可重用代码的最佳实践。我在开发人员中遇到了一个我还不太了解的常见做法 public MyConstructor(Object myObject) { if (myObject == null) throw new ArgumentNullException("myObject is null."); _myObject = myObject; } 几乎没有必要做这项检查。但我认为这是因为我不完全明白做这个检查的好处是什么。似乎无论如何都

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

public MyConstructor(Object myObject)
{
    if (myObject == null)
        throw new ArgumentNullException("myObject is null.");
    _myObject = myObject;
}
几乎没有必要做这项检查。但我认为这是因为我不完全明白做这个检查的好处是什么。似乎无论如何都会抛出空引用异常?我可能错了,真的很想听听大家的想法


谢谢。

编译器不知道对象的值,因此您必须在运行时对此进行检查,以确保不会使用空值调用它


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

我认为,一般来说,不可能判断是否需要检查null。这完全取决于您是否能够使用空值变量。Null本身并不是一个坏状态。在某些情况下,允许变量为null,而在其他情况下则不允许


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

传递一个
null
对象在许多情况下是完全合法的-对于这个类,实现者希望确保您不能创建一个不传递有效
对象
实例的类实例,因此以后不必进行检查-最好尽早确保这一点,这将在构造函数中进行。

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

对于编译器来说,
null
是合法的构造函数参数


您的类可能能够为
myObject
处理空值。但是如果不能,如果你的类在
myObject
为空时会中断,那么签入构造函数就允许你这样做。

好处是异常将在对象构造时抛出,因此你可以很容易地跟踪代码的哪一部分是罪魁祸首。如果您的代码需要非空的
myobject
值,并且您没有在构造函数中验证它,当您使用
myObject\uu
时,将抛出
NullReferenceException
,您必须手动回溯以查看是谁发送了该空值。

您可以实现一个简单的
ThrowIfNull
扩展方法来减少每次编写的代码。Jon Skeet在其及其引用的SO文章中介绍了这一点。

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

 public ctor(IEnjection ninjaWeapon) 
 {
     Contract.Requires<ArgumentNullException>(ninjaWeapon != null);
     this.deadlyWeaponary.Add(ninjaWeapon);
 }
public-ctor(IEnjection-ninja)
{
契约。要求(Ninja武器!=null);
这个。致命武器。添加(忍者武器);
}

如果您使用的是旧版本,请参考Microsoft.Contract来执行相同的操作。

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

如果不需要
null
参数,则可以从C#7.0中使用抛出表达式,使我们能够更简洁地重写
null
检查代码,如下例所示:

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

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

不需要您执行的操作,您可以在引用对象之前检查以确保该对象不为null。当然,验证对象初始化时将使用的内容是一种非常有效的方法。@Ramhound-这是使用DI框架(如StructureMap)时的一种常见方法,您不必直接控制传递给构造函数的内容。如果您的类没有
myObject
是无用的,并且这是初始化它的唯一地方,那么尽早抛出异常是有意义的,这样您就可以了解它们。在一个长时间运行的web应用程序中,你可能不知道这个问题,直到有人碰巧调用了一个需要该对象的方法。解释得很好。我特别喜欢“快速失败”这个词。谢谢你的见解。博客链接断开了,但我想这是同一篇文章:但如果代码契约没有在编译后的步骤中重写,它们将一事无成。