3

我正在做一些有问题的作业:

你会如何前置条件例外?
您将如何使用后置条件异常?

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

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

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

任何人都可以为此提供一个例子吗?

4

2 回答 2

6

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

我会将 a 解释Post-Condition Exception为引发异常的操作(直接使用throw或使用 guard Assert),而不是仅仅轻轻地返回失败的返回码或默认值,调用者可能不会检查这些值。

硬故障在检查前置条件、后置条件和不变量时至关重要,因为调用者需要检查(并且可能会错过)软返回(例如false0-1之类的魔法值)并掩盖代码在设计外状态下运行的真正问题。

以下示例希望说明使用异常的后置条件。在我的简单设计中Square(x),只要输入的契约是有效的(即输入数字的平方不会溢出),函数应该保证结果是一个正数。如果后置条件检查失败,则意味着我的设计/实现中存在缺陷,这可能会产生可怕的后果(例如,没有考虑到的场景,或依赖项失败,例如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. 这样做的好处是,在方法的顶部记录了前置条件和后置条件,并且还避免了对额外局部变量的需要,因为可以直接“检查”结果:

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;
}

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

于 2014-05-11T07:54:29.323 回答
5

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

我也从未听说过它被称为“后置条件异常”,但至于您的问题,“它们何时使用”,它们在单元测试中被大量使用(参见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方法调用中抛出,在调用被测方法后,属于后置条件异常。

于 2014-05-11T08:31:44.487 回答