29

我一直在使用新的 System.Diagnostics.Contracts 类,因为它起初看起来非常有用。检查入站参数、返回值等的静态方法。它是一个干净的接口,可以替换许多 if-then 语句和内部构建的库工具。

但是,在大多数运行时情况下,它似乎没有多大用处。据我所知,它不会引发错误,所以我无法得知合同是否失败。它会弹出一个带有错误的对话框。如果我在一个很少有人看的远程机器上运行 wcf 服务……我怎么知道合同失败了?如果我不能捕捉到错误发生的事实,我怎么能让服务的调用者知道他们搞砸了?

Throw-Catch 已经存在了一段时间,我不明白为什么 Contracts 想要绕过它。我是否试图错误地使用这个东西?如果是这样,那么有人给了我一个运行时合约有意义的真实情况。肯

4

1 回答 1

38

据我所知,它不会引发错误,所以我无法得知合同是否失败。

如果你需要抛出一个特定的异常来调用代码来捕获,那么你应该使用Contract.Requires<TException>方法或遗留的 if-then-throws 后跟Contract.EndContractBlock(). 例如,当其他代码已经期望并依赖于抛出的常规异常时,您将执行此操作。

有关何时使用不同形式的前置条件的完整说明,请参阅用户手册第 5.1 节:参数验证和合同。

它会弹出一个带有错误的对话框。

如果您在项目设置的“代码合同”选项卡中取消选中“合同失败时断言”,您将在调试时在代码中的违规点抛出一个实际异常,而不是一个对话框。然而,这不是为了捕捉。

Throw-Catch 已经存在了一段时间,我不明白为什么 Contracts 想要绕过它。我是否试图错误地使用这个东西?如果是这样,那么有人给了我一个运行时合约有意义的真实情况。

用户手册第 7.5 节:运行时行为的合理性第 7.6 节:ContractException解释了为什么它以这种方式运行。

这个想法是,您永远不需要编写包含处理违反合同的特定逻辑的程序。它们绝不应该出现在正确的程序中,并且表明代码中存在需要修复的严重错误。这类似于您应该如何避免捕获ArgumentNullException.

在不表示代码本身错误的特殊情况下,您仍应抛出常规异常,例如找不到文件时。这允许调用代码适当地处理该情况。

如果我在一个很少有人看的远程机器上运行 wcf 服务……我怎么知道合同失败了?

最好在使用该软件之前尽可能多地对其进行测试,以确保它永远不会违反任何合同。

如果您有特殊需要覆盖运行时行为,您可以通过编写自己的合约运行时类来实现。有关详细信息,请参阅用户手册第 7.7 节:提供自定义合同运行时类

编辑:回应下面的评论......

你说是找代码的毛病,但代码中的毛病大多来自外部传入的数据,而不是代码的毛病。并且软件需要同时记录有人传递了错误数据的事实,并告诉他们他们传递了错误数据,以便他们可以修复它。

前置条件是定义何时允许调用方法的合同,并且意味着在调用方法时由调用者验证。运行时检查器将在调用代码中注入适当的检查,而不是方法本身。如果您有可用的静态检查器,它会在您未能确保调用该方法之前的先决条件时向您指出。

在您的情况下,您处理数据的内部方法应该定义先决条件,说明它们允许什么样的数据。当数据从您无法控制的外部来源传入时,您应该对其进行验证并以通常的方式进行处理;您不想为此使用代码合同。但是,例如,如果您忘记完全验证该数据,那么在使用前置条件调用内部代码时,您将遇到合同违规。这表明您自己的代码中存在错误

于 2010-08-06T20:31:49.723 回答