2010-07-14 80 views
5

我经常拥有调用层次结构,因为所有方法都需要相同的参数。如果我不想将它们放在实例级别(类的成员),那么我总是问我是否有意义在每种方法中检查它们的有效性。函数中的重复参数检查

例如:

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也检查的优势可能是异常抛出被调用者调用的方法,这很好,但它是否有必要?调用堆栈也会说明这一点。也许它的意义在公共,内部,受保护但不是私人方法?

我以空检查为例,但索引验证或范围验证属于自我问题,但我认为由于冗余代码的危险而存在限制。你怎么看?

UPDATE

通过我已经看到了,我是有点精确AakashM的答案。 MethodA不仅呼叫MethodB,它也做其他事情,但不涉及o。我添加了一个例子来澄清这一点。谢谢AakashM。

回答

9

史蒂夫麦康奈尔的代码完整谈论'路障'的概念 - 一个防御墙外的数据是不可信的,内部的数据是值得信赖的。想要进入路障的数据必须经过验证过程,但是在路障中,数据可以随意通过验证码自由移动。

如果你可以在你的项目中加入这样的构造和分层,并且坚持下去,它确实会使内部代码的代码更少,更精髓。但是只需要一种方法就可以调用路障来防止出错。

在你的例子中,MethodBpublic。这意味着你没有自动的未来保证MethodA将成为它的唯一调用者 - 因此我会说它的验证码应该保留。但是,如果它是private,那么您可以为删除它做一个参数。

至于MethodA,如果它实际上没有没有多于致电MethodB,它应该不存在。如果它是未来扩展的存根,并且在某些时候它将与o做些什么,那么它的验证代码也应该保留。

1

我认为你应该确保它一旦产生输入值(调用者的责任)。如果该类仅由内部客户端使用,这将起作用。如果它是公共API的一部分,那么您不能退出支票,但您可能需要将它们分解,正如其他答案中所述。

出于测试目的,您也可以在两种方法中使用Debug.Assert(o != null),如果性能问题,检查将从发布代码中删除。

+0

产生输入值的地方 - 在调用者意味着什么?我想要写我的例子的例子是,方法A和B都可以从类的外部访问,并且它的合法调用其中的一个(MethodA执行相同,比MethodB稍微多一点) – HCL 2010-07-14 11:01:53

+0

是的。看我的编辑。 – Mau 2010-07-14 11:21:16

1

我不认为参数验证“冗余代码”。您需要保护所有外部入口点。如果你有一个private的方法,这样你就知道时间流程到了它的所有参数都会有效,那么你可能有一个例子,但是对于public(甚至protected)方法你真的不会。