C# 我什么时候应该防止空值?

C# 我什么时候应该防止空值?,c#,C#,我应该在什么时候防范null参数?理想情况下,我会在任何地方防止null,但这会变得非常臃肿和乏味。我还注意到,人们并没有在AsyncCallbacks之类的东西中设置防护 为了避免用大量单一的代码来烦扰其他人,我应该在哪里防范null,有什么公认的标准吗 谢谢。必须检查公共API的空值。对于开发人员来说,如果他们一开始就知道自己有一个由null参数引起的错误,而不是试图调试该null参数导致的一些模糊的其他异常,那么会更容易(也更安全) 在内部,构造函数是检查空值的好地方,原因也是一样的——在

我应该在什么时候防范
null
参数?理想情况下,我会在任何地方防止
null
,但这会变得非常臃肿和乏味。我还注意到,人们并没有在
AsyncCallback
s之类的东西中设置防护

为了避免用大量单一的代码来烦扰其他人,我应该在哪里防范
null
,有什么公认的标准吗


谢谢。

必须检查公共API的空值。对于开发人员来说,如果他们一开始就知道自己有一个由null参数引起的错误,而不是试图调试该null参数导致的一些模糊的其他异常,那么会更容易(也更安全)

在内部,构造函数是检查空值的好地方,原因也是一样的——在构造函数中捕获空值比在类上调用方法时更容易


有些人认为到处检查是好的,但我倾向于认为在实际阅读代码时,它会使更多的代码需要筛选。

有时我会创建一个
预条件
类,其中包含用于检查一些常用方法预条件的静态方法,例如,一个
null
参数——例如:

public static <T> T checkNull(T arg) {
    if (arg == null)
        throw new IllegalArgumentException();
    return arg;
}
公共静态T checkNull(T arg){
如果(arg==null)
抛出新的IllegalArgumentException();
返回arg;
}
这会使代码更整洁

至于您应该在哪里检查
null
,应该在它不是有效值的地方进行检查

编辑


注意到这个问题被标记为C#,但是你明白了…

如果你谈论的是方法参数,你有一个选择。您可以检查参数并抛出
ArgumentNullException
,也可以忽略该检查并让其他内容抛出
NullReferenceException
。不检查参数的风险在于,在抛出
NullReferenceException
之前,代码可能会更改某些全局状态,使程序处于未知状态

通常,最好检查方法抛出的参数和文档
ArgumentNullException
。是的,这需要更多的工作,而且在方法开始时费力地通过这些检查可能会很烦人。您必须扪心自问,在exchange中获得的更健壮的代码是否是一个好的折衷方案


有关此问题的详细讨论,请参阅。

我经常使用的一种方法是 例如,如果有一个工厂类,它根据参数返回接口的不同实现,并且提供的参数未映射到任何实现,我将返回一个NullObject, e、 g

当我想从
CreateFoo
获取
IFoo
时,我不必检查返回的对象是否为null

显然,这只是众多方法中的一种。不存在“一刀切”的情况,因为null可以表示不同的内容

另一种防止空参数的方法是使用。 e、 g

然后你可以像这样检查你的论点:

 public void Foo(Bar x, Bar y){
     x.EnsureNotNull("x");
     y.EnsureNotNull("y");
 }
我什么时候应该防止空参数

我将假设您正在谈论传递给已编写代码的公共方法或构造函数的空参数。请注意,在调用任何可能返回null的外部依赖项时,您可能还必须“防范”null,除非您的代码能够优雅地处理这些情况

在向用户公开的任何public方法(包括构造函数和属性设置器)中,如果null值没有有用的明确含义,则应防止出现null。如果空值对代码没有特殊意义(例如数组末尾,“未知”等),则不应接受该值,而应抛出
ArgumentNullException

此规则对于
null
也不是唯一的。您应该始终检查传递给公共方法的参数

例如,假设您正在编写某种web服务方法,该方法接受用户Id,并对用户执行某些操作(例如删除它们)。在方法对该用户执行任何其他操作之前,您应该验证它是否是有效的用户Id。另一个例子是,如果您正在编写一个公共方法,该方法对集合或数组进行索引。您应该预先检查索引是否在允许的范围内-索引是否大于集合,或者是否小于零

我还注意到,人们并没有在异步回调之类的东西中设置防护

如果您知道传递给您的方法的参数会小心地保留您的方法的先决条件(因为如果没有,您会抛出异常),那么您可以自由地跳过私有和内部方法或私有和内部类中的这些检查

但正如您所指出的,您仍然必须小心,不要信任来自您未编写的API的任何返回值,或者任何传入回调方法的值。将它们视为“脏”,并假定它们可以是空值或无效值

那会变得非常臃肿和乏味

为公共方法指定并跟踪前置条件并不是一件小事,而是编译文档。这就是你如何确保你的代码是正确的。这就是你的代码的用户被预先告知他们做了错事的方式。在你的方法中间(或者在一些模糊相关的类中的另一个方法中),这会使调试问题变得困难得多。

现在看来这似乎不是什么大事。但是,一旦你开始收到客户对
NullReferenceException
5级异常的投诉,20次方法调用之后,我想你就会开始看到好处:)

为了避免用大量不规范的代码来烦扰其他人,是否有任何公认的标准来防止空代码

通常,如果。。。抛出
  public void Foo(Bar x){
      Contract.Requires<ArgumentNullException>( x != null, "x" );
      //access x
  }
public static class Ex
{
    public static void EnsureNotNull<T>(this T t, string argName) where T:class
    {
        if(t == null)
        {
            throw new ArgumentNullException(argName);
        }
    }
}
 public void Foo(Bar x, Bar y){
     x.EnsureNotNull("x");
     y.EnsureNotNull("y");
 }