什么是后置条件异常



我正在做一些作业,其中有一个问题:

如何处理前置条件异常?
如何使用后置条件异常?

对于第一个问题,我假设前提条件是为了使函数运行而必须满足的东西。例如,参数不能为空,可以抛出异常:

if (myArg == null)
    throw new ArgumentNullException("myArg");
//do work here

然而,我不明白后置条件异常的用途是什么,以及为什么我们要在这种情况下抛出异常(例如,如果不满足条件而不是返回false)。

谁能提供一个例子吗?

后验条件是一段代码(如方法或函数)在退出函数时给出的状态保证,如返回值的正确性,或更广泛状态的正确性,如类实例甚至整个程序的状态。

我将Post-Condition Exception解释为抛出异常的动作(直接使用throw,或使用保护Assert),而不仅仅是软返回失败的返回代码,或默认值,这可能不会被调用者检查。

硬故障在检查前置条件、后置条件和不变量方面是至关重要的,因为软返回(例如像false0-1这样的魔术值)需要被调用者检查(并且可能被忽略),并且掩盖了代码在非设计状态下运行的真正问题。

下面的示例有望说明使用异常的post条件。在我对Square(x)的简化设计中,假设输入上的契约是有效的(即输入数的平方不会溢出),该函数应该保证结果是正数。如果post条件检查失败,这意味着我的设计/实现中存在缺陷,可能会产生可怕的后果(例如,没有想到的场景,或者依赖项的失败,例如Math库本身)。

异常示例:

public static double Square(double number)
{
   // Pre condition
   if (Math.Abs(number) > Math.Sqrt(double.MaxValue))
       throw new InvalidArgumentException("Number too big - will overflow");
   var result = number * number;
   // Post condition
   if (result < 0)
       throw new Exception("Square(x) should always be positive!");
   return result;
}

根据注释,代码契约还允许通过Contract.Ensures指定post条件。这样做的好处是,前置和后置条件都记录在方法的顶部,并且还避免了对额外的局部变量的需要,因为结果可以直接"检查":

public static double Square(double number)
{
   Contract.Requires(Math.Abs(number) < Math.Sqrt(double.MaxValue), 
      "Oops number will result in overflow");
   Contract.Ensures(Contract.Result<double>() >= 0, 
      "Square should always be positive!");
   return number * number;
}

代码契约相对于基于异常的断言的另一个优点是静态检查——契约可以在编译后进行验证。

另一个答案是正确的,评论对回答你的问题都很有用。我觉得有一点可以补充的,所以这是我的贡献。

我也从来没有听说过它被称为"后条件异常",但至于你的问题,"什么时候使用它们",它们在单元测试中使用得很多(参见https://stackoverflow.com/tags/unit-testing/info或其他资源,如维基百科的操作方法)。在单元测试中,测试程序员调用她想要测试的函数,并且她也知道她期望从函数中得到什么值(也就是说,从其他知识来源知道答案是正确的)。后置条件测试是:"从函数或方法返回的期望值和实际值是否一致?"

如果它们不一致,则Assert方法抛出异常。测试框架软件捕获异常,然后将给定的测试报告为失败,并继续运行其他测试,而不会在失败的测试上停止。下面是一个简单的例子。

[TestMethod]
public void Integers_7Add1_equals8()
{
   int expected = 8;
   int actual = MyClass.AddOne(7);
   Assert.AreEqual(expected, actual);
}

异常在Assert中抛出。在调用被测试的方法之后调用AreEqual方法,因此它是一个后置条件异常。

相关内容

  • 没有找到相关文章

最新更新