C# 何时检查空值
这是一个开放式的问题,但我正试图通过良好的异常处理实践来提高我的技能,特别是在一般情况下检查空值的时候 我知道什么时候检查空值,但我不得不说一半时间我不知道,这让我很烦恼。我知道除非使用可为null的int,否则int不能设置为null。我知道字符串可以设置为null或空,因此可以检查IsNullOrEmpty 显然,在构造函数中,您也希望在其中添加显式检查。这是必然的。我认为在将数组、泛型对象或其他对象传递到可以设置为null的方法中时,应该检查null,基本上正确吗 但是这里有更多的异常处理。例如,我不知道何时总是在代码中明确地检查并抛出null ref异常。如果我有传入的参数,通常是非常直接的,但总有一些情况下我会问自己,是否需要显式的null抛出C# 何时检查空值,c#,exception-handling,C#,Exception Handling,这是一个开放式的问题,但我正试图通过良好的异常处理实践来提高我的技能,特别是在一般情况下检查空值的时候 我知道什么时候检查空值,但我不得不说一半时间我不知道,这让我很烦恼。我知道除非使用可为null的int,否则int不能设置为null。我知道字符串可以设置为null或空,因此可以检查IsNullOrEmpty 显然,在构造函数中,您也希望在其中添加显式检查。这是必然的。我认为在将数组、泛型对象或其他对象传递到可以设置为null的方法中时,应该检查null,基本上正确吗 但是这里有更多的异常处理
我并没有具体的例子,但我想知道是否有一个很好的参考文献,真正涉及到何时抛出异常处理(在方法、类内部,你可以这么说)。你不应该抛出
NullReferenceException
。如果参数为null,则改为抛出ArgumentNullException
我更喜欢检查public/protected方法的所有引用类型参数是否为null。对于私有方法,如果您确定所有调用始终具有有效数据,则可以省略检查 除非您使用的是代码契约,否则最好检查任何公共/受保护成员的参数,并明确记录它们是否可以为null。对于私有/内部方法,验证您自己的代码而不是其他人的。。。在这一点上,这是一个判断 我有时会为此使用助手扩展方法,因此我可以编写:
public void Foo(string x, string y, string z)
{
x.ThrowIfNull("x");
y.ThrowIfNull("y");
// Don't check z - it's allowed to be null
// Method body here
}
ThrowIfNull
将抛出具有适当名称的ArgumentNullException
通过在进行任何其他调用之前进行显式检查,您知道如果抛出异常,则不会发生任何其他情况,从而不会出现损坏状态
我承认我会忽略这样的检查,因为我确信第一次调用会执行相同的检查——例如,如果是一个过载负载在另一个过载负载上
对于代码契约,我会写:
public void Foo(string x, string y, string z)
{
Contract.Requires(x != null);
Contract.Requires(y != null);
// Rest of method here
}
这将抛出一个ContractException
,而不是ArgumentNullException
,但所有信息仍然存在,并且无论如何都不应该有人显式捕获ArgumentNullException
(可能是为了应对第三方不良行为)
当然,是否允许空值的决定是完全不同的。这完全取决于形势。防止空值进入您的世界确实使某些事情变得更容易,但同时空值本身也很有用。我的经验法则是:
- 始终检查传递给任何类的公共/受保护方法的参数
- 始终检查构造函数和初始化方法的参数
- 始终检查索引器或属性设置器中的参数
- 始终检查作为接口实现的方法的参数
- 对于多个重载,尝试将所有参数预条件放在其他重载委托给的单个方法中
NullReferenceExceptions
要好得多
如果(arg==null)抛出新的ArgumentNullException(…),可以使用实用程序方法清理典型的代码>构造。您可能还希望研究C#4.0中的代码,以改进代码。代码契约执行静态和运行时检查,即使在编译时也可以帮助识别问题
一般来说,编写方法的前提条件是一种耗时的做法(因此经常被忽略)。但是,这种防御性编码的好处在于,由于您没有验证输入,因此可能会节省数小时的调试时间
作为旁注,是一个很好的工具,用于识别对参数或本地成员的潜在访问,这些参数或本地成员在运行时可能为空。越早越好。你越快抓住(无效)空,你就越不可能在某个关键过程中抛出。另一个需要考虑的事情是使用您的属性(SETTES)集中验证。我经常在构造函数中引用我的属性,因此我在验证中得到了很好的重用
class A
{
private string _Name
public string Name
{
get { return _Name; }
set
{
if (value == null)
throw new ArgumentNullException("Name");
_Name = value;
}
}
public A(string name)
{
//Note the use of property with built in validation
Name = name;
}
}
取决于方法/api/库/框架的类型。我认为私有方法可以不检查空值,除非它们是一种断言方法
如果你编写防御性的程序,并且在代码中乱扔“NOTNULL”-测试或“If”-语句,那么你的代码将无法读取
定义客户端通过提交错误的/空的/空的参数而使代码混乱的区域。如果你知道在哪里,你可以画一条线在哪里做你的空检查。在api入口点执行此操作,就像在现实生活中安全工作一样
想象一下,如果你每分钟都在电影院里出示门票,那么每部电影都会很糟糕。我更喜欢使用静态模板方法来检查输入约束。一般的格式如下:
static class Check {
public static T NotNull(T arg) {
if( arg == null ) throw new ArgumentNullException();
}
}
使用它的好处是,您的方法或构造函数现在可以使用Check.NotNull()包装参数的第一次使用,如下所示:
this.instanceMember = Check.NotNull(myArgument);
当我使用.NET4时,我可能会转换为代码契约,但在此之前,这是可行的。顺便说一句,您可以在以下url找到我使用的检查类的更完整定义:
值得一提的是,.NET代码契约的一大好处是