我一直在玩新的System.Diagnostics.Contracts类,因为它起初看起来非常有用。用于检查入站参数,返回值等的静态方法。它是一个干净的接口,可以替换许多if-then语句和内部构建的库工具。
但是,它在大多数运行时情况下似乎不太有用。据我所知,它不会引发错误,所以我无法知道合同是否失败。它会弹出一个带有错误的对话框。如果我在远程盒子上运行wcf服务,很少有人看它...我怎么知道合同失败了?如果我无法捕捉错误发生的事实,我怎么能让服务的来电者知道他们已经搞砸了呢?
Throw-Catch已经存在了一段时间,我不明白为什么Contracts想绕过这个。我试图错误地使用这个东西吗?如果是这样,那么有人会给我一个真实的情况,其中运行时契约是有意义的。 肯
答案 0 :(得分:37)
据我所知,它不会引发错误,所以我无法知道合同是否失败。
如果你需要抛出一个特殊的异常来调用要捕获的代码,那么你应该使用Contract.Requires<TException>
方法或遗留的if-then-throws后跟Contract.EndContractBlock()
。例如,当其他代码已经期望并依赖于抛出的常规异常时,您就会执行此操作。
有关何时使用不同形式的前提条件的完整说明,请参阅{{3>}的第5.1节:参数验证和合同。
弹出一个带错误的对话框。
如果在项目设置的“代码合同”选项卡中取消勾选“合同失败时断言”,则在调试时会在代码中的违规点处抛出实际异常,而不是对话框。但是,这不是为了捕捉。
Throw-Catch已经存在了一段时间,我不明白为什么Contracts想绕过这个。我试图错误地使用这个东西吗?如果是这样,那么有人会给我一个真实的情况,其中运行时契约是有意义的。
第7.5节:运行时行为的Rational 和 user manual的第7.6节:ContractException 解释了为什么它以这种方式运行。
这个想法是你永远不需要编写包含处理合同违规的特定逻辑的程序。它们永远不应该出现在正确的程序中,并指出需要修复的代码中的严重错误。这与您应该避免捕获ArgumentNullException
的方式类似。
在不表示代码本身存在错误的特殊情况下,例如无法找到文件时,您仍应抛出常规异常。这允许调用代码在适当的时候处理这种情况。
如果我在远程盒子上运行wcf服务,很少有人看它...我怎么知道合同失败?
最好在使用之前尽可能多地测试软件,以确保它永远不会违反任何合同。
如果您特别需要覆盖运行时行为,则可以通过编写自己的合同运行时类来实现。有关详细信息,请参阅{em>第7.7节:提供user manual的自定义合同运行时类。
编辑:回复以下评论......
你说这是为了在代码中找到错误,但是代码中的大多数错误来自从外部源传入的数据,而不是代码错误。软件需要同时记录有人传入错误数据的事实,并告诉他们他们传递了错误的数据,以便他们可以修复它。
前提条件是定义何时调用允许方法的合同,并且在调用方法时由调用者进行验证。运行时检查器将在调用代码中注入适当的检查,而不是方法本身。如果您有可用的静态检查程序,只要您在调用该方法之前未能确定先决条件,它就会指出您。
在您的情况下,处理数据的内部方法应定义前提条件,说明它们允许哪种数据。当数据从您无法控制的外部源传入时,您应该验证它并以通常的方式处理它;你不想为此使用代码合同。但是,如果您忘记完全验证该数据,则在使用前置条件调用内部代码时,您将遇到合同违规。这表示您自己的代码中存在错误。