15

我想知道,代码验证方法的参数在哪里——以及多久一次。

在下面的示例类(一个 .dll 库)中,您认为最好的方法是什么?假设我想验证某个对象不能是null(但它可以是方法正常运行所需的任何其他验证)。在第 1 点中只检查一次是否更好,在用户可用的公共方法中,然后“相信我自己”,在其他私有方法中它不会为空,或者,最好有点偏执并检查它使用它的时间(在第 2、3 和 4 点)

在使用对象之前检查它(在第 2、3、4 点中)可以在将来保护我,如果我决定使用这些私有方法更改类中的某些内容,并“忘记”传递有效对象。如果我将来添加一些新的公共方法,我也不必记住验证。另一方面 - 它一遍又一遍地检查相同的条件。或者,也许您还有其他建议?

public class MyClass()
{
    public MyClass()
    {
    }

    public void ProcessObject(SomeObject obj)
    {
        //1. if (obj == null) throw new ArgumentException("You must provide valid object.");

        DoSomething(obj);
        DoMore(obj);
        DoSomethingElse(obj);
    }

    private void DoSomething(SomeObject obj)
    {
        //2. if (obj == null) throw new ArgumenException("You must provide valid object.");
        //do something with obj...
    }

    private void DoMore(SomeObject obj)
    {
        //3. if (obj == null) throw new ArgumentException("You must provide valid object.");
        //do something with obj...
    }

    private void DoSomethingElse(SomeObject obj)
    {
        //4. if (obj == null) throw new ArgumentException("You must provide valid object.");
        //do something with obj..
    }
}  
4

3 回答 3

12

如果它是您公开供其他开发人员使用的 API,那么您确实应该在每个方法上抛出ArgumentExceptionArgumentNullException.

如果它是其他开发人员不会直接与之交互的内部类或方法,我会使用Debug.Assert,因此在调试模式下,您可以获得额外的调试信息,而在发布模式下,它会被取消,并且您会获得不执行所有这些参数的性能优势到处检查。

于 2012-06-17T18:51:39.563 回答
5

在一个好的软件设计方法中需要相互独立。您必须能够以任何顺序使用它们并且彼此分开。所以是的,你必须一遍又一遍地检查所有方法中的相同条件。

编辑: 我会将 CodeContract 与一个检查 obj 不为空的前提条件一起使用。因为这似乎是方法正常工作的先决条件。

于 2012-06-17T18:51:10.280 回答
3

每个公共方法都应该验证其输入。

恕我直言,如果您只是传递先前验证的对象,则私有方法可以依赖于对类中其他公共方法的验证。由于私有方法封装在类中,因此验证的责任留在类中。

但是,如果您有一个私有方法接受一些计算参数(而不是传递给公共方法的参数),那么应该进行额外的验证。

您的单元测试将测试该类的公共接口,如果您SomeObjectnull验证仅在ProcessObject. 在那种情况下,我不会在私有方法中重复验证。

于 2012-06-17T18:48:46.757 回答