我经常调用层次结构,因为所有方法都需要相同的参数。如果我不想把它们放在实例级别(类的成员),那么我总是问我是否有意义检查每种方法中它们的有效性。
例如:
public void MethodA(object o){
if(null == o){
throw new ArgumentNullException("o");
}
// Do some thing unrelated to o
MethodB(o);
// Do some thing unrelated to o
}
public void MethodB(object o){
if(null == o){
throw new ArgumentNullException("o");
}
// Do something with o
}
如果Method
A使用参数,那么它清楚,我必须检查那里的有效性以及MethdoB。但只要MethodA不再对o
执行操作而不是将其提交给MethodB
,在MethodA
中检查有效性也是一种好习惯。
MethodA
中检查的优势可能是被调用方调用的方法中抛出异常,这很好,但是有必要吗?调用堆栈也会说明这一点。也许它有意义的公共,内部,受保护但不是私人方法?
我以空值检查为例,但索引验证或范围验证也属于自我问题,但我认为由于存在冗余代码的危险,因此存在局限性。你觉得怎么样?
更新
通过AakashM的回答,我看到我的确很精确。 MethodA
不仅会调用MethodB
,还会调查与o
无关的其他内容。我添加了一个例子来澄清这一点。谢谢AakashM。
答案 0 :(得分:9)
如果你可以在你的项目中强加这么多的结构和分层,并坚持下去,它确实会使内部的路障代码有更少的仪式和更多的本质。但是只需要一种方法来控制路障就会出错。
在您的示例中,MethodB
为public
。这意味着您没有自动将来保证MethodA
将成为其唯一的调用者 - 因此我会说它的验证代码应该保留。但是,如果该类为private
,则可以进行删除它的参数。
至于MethodA
,如果它实际上 ,而不是调用MethodB
,则它不应该存在。如果它是未来扩展的存根,并且在某些时候它会对o
执行某些操作,那么它的验证代码也应该保留。
答案 1 :(得分:1)
我认为你应该确保产生输入值的一次(来电者的责任)。如果该类仅由内部客户端使用,则此方法有效。如果它是公共API的一部分,那么你无法逃避检查,但你可能想要将它们分解,如其他答案所示。
出于测试目的,您还可以在两种方法中使用Debug.Assert(o != null)
,并且将从发布代码中删除检查,如果性能是个问题。
答案 2 :(得分:1)
我不认为参数验证是“冗余代码”。您需要保护所有外部入口点。如果您有一个private
方法,以便通过时间流知道它的所有参数都将有效,那么您可能有一个案例,但public
(甚至{{} 1}})你真的没有的方法。