在我的脑海中,我可以想到4种方法来检查空参数:
Debug.Assert(context != null);
Contract.Assert(context != null);
Contract.Requires(context != null);
if (context == null) throw new ArgumentNullException("context");
我一直使用最后一种方法,但我刚看到一个使用Contract.Requires
的代码片段,我对此并不熟悉。 每种方法有哪些优点/缺点?还有其他方法吗?
在VS2010 w / Resharper中,
Contract.Assert
警告我表达式总是正确的(它怎么知道,我不太确定...... HttpContext不能为空?),Contract.Requires
逐渐消失,它告诉我编译器不会调用该方法(我假设因为前一个原因,它永远不会为null),并且context != null
,则后面的所有代码都会逐渐消失,它会告诉我代码是启发式无法访问的。 所以,似乎最后3种方法在VS静态检查器中内置了某种智能,而Debug.Assert
只是愚蠢。
答案 0 :(得分:12)
我的猜测是,有一个契约应用于接口IHttpHandler.ProcessRequest,需要上下文!= null。接口契约由其实现者继承,因此您无需重复Requires。实际上,您不能添加其他Requires语句,因为您仅限于与接口契约相关的要求。
我认为在指定合同义务与简单执行空检查之间进行区分非常重要。您可以在运行时实现空检查并抛出异常,以通知开发人员他们正在使用您的API。另一方面,契约表达式实际上是一种元数据形式,可以由合同重写器解释(引入先前手动实现的运行时异常),也可以由静态分析器解释,静态分析器可以使用它们来推理关于你的申请的静态正确性。
也就是说,如果您在一个正在积极使用代码约定和静态分析的环境中工作,那么将这些断言置于契约形式中是绝对可取的,以利用静态分析。即使您没有使用静态分析,您仍然可以通过使用合同为以后的利益敞开大门。需要注意的是,您是否已将项目配置为执行重写,否则合同将不会像您预期的那样导致运行时异常。
要详细说明评论者所说的内容,Assert,Assume和Requires之间的区别是:
答案 1 :(得分:2)
第一种方法适用于测试永远不存在的空条件。也就是说,在开发期间使用它以确保它不会意外地设置为null。由于它不执行任何错误处理,因此不适合处理已发布产品中的空条件。
我想说第二版和第三版的相似之处在于他们不会以任何方式处理这个问题。
通常,如果变量在最终产品中实际上可能为空,则最后一个版本是要使用的版本。你可以在那里做特殊处理,或者只是像你一样提出异常。