什么是后置条件异常?

3
我正在做一些关于IT技术的作业,其中有一个问题:
你如何处理前置条件异常?
你如何处理后置条件异常?
关于第一个问题,我认为前置条件是指函数运行所必需满足的条件。例如,如果参数不应为空,则可以抛出异常:
if (myArg == null)
    throw new ArgumentNullException("myArg");
//do work here

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

有人能提供一个例子吗?


C#没有本地的前/后条件 - 但是,请参见代码合同:“代码合同提供了一种在您的代码中指定先决条件,后置条件和对象不变式的方法。先决条件是进入方法或属性时必须满足的要求。后置条件描述了方法或属性代码退出时的期望。对象不变量描述了处于良好状态的类的预期状态。” - user2864740
我已经编辑了你的标题。请参考“问题标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
http://msdn.microsoft.com/en-us/library/dd264808(v=vs.110).aspx - David Brabant
就“为什么”而言,我认为这主要是从像Eiffel这样的语言的视角中根深蒂固的:ET: Design by Contract (tm), Assertions and Exceptions(作者Bertrand Meyer撰写了几篇论文并教授该主题)。 - user2864740
我从未听说过“后置条件异常”这个术语。你是从哪里得到的?“后置条件”是业界常用的术语。 - Sriram Sakthivel
@SriramSakthivel 这是我面向对象编程课程作业的一部分。 - Brugsen
2个回答

6
一个后置条件是关于代码状态的保证,例如方法或函数退出时返回值的正确性,或更广泛的状态,例如类实例或整个程序的状态的正确性。
我认为“后置条件异常”指的是抛出异常的操作(直接使用throw或使用守卫Assert),而不仅仅是软性返回失败的返回码或默认值,因为调用者可能不会检查这些值。
在前置条件、后置条件和不变量的检查中,硬性故障至关重要,因为软性返回需要由调用者检查(并可能被忽略),并掩盖了“代码正在以非设计状态运行”的真正问题。
以下示例希望用异常说明后置条件。在我简单的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;
}

根据评论,Code Contracts还允许通过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;
}

与基于异常的断言相比,代码契约具有的另一个优势是静态检查- 契约可以在编译后立即验证。


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方法调用中引发异常,因此这是一个后置条件异常。

1
好的回答,这可能是我们在我的课堂上进行单元测试后使用异常的原因之一 - 我只是没有将Assert.AreEqual()视为后置条件异常,但当你考虑它时,基本上就是这样做的。谢谢。+1 - Brugsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接