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

但是,在大多数运行时情况下,它似乎没有用。据我所知,它不会引发错误,因此我无法捕捉到任何信息以了解契约(Contract)是否失败。它会弹出一个错误对话框。如果我在很少有人看的远程机器上运行wcf服务...我怎么知道契约(Contract)失败了?如果我不能捕获错误发生的事实,我如何让服务的调用者知道他们的错误?

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

最佳答案



如果需要引发特定异常以调用代码以进行捕获,则应使用Contract.Requires<TException>方法或传统的if-then-throws后面紧跟Contract.EndContractBlock()。例如,当其他代码已经期望并且依赖于抛出常规异常时,您将执行此操作。

有关何时使用不同形式的前提条件的完整说明,请参见user manual的5.1节:参数验证和契约(Contract)。



如果取消项目设置的“代码契约(Contract)”选项卡中的“契约(Contract)失败声明”,则在调试时会在代码的问题点而不是对话框中抛出实际的异常。但是,这不是要捕获的。



user manual的第7.5节:运行时行为的合理性和第7.6节:ContractException解释了为什么这种方式起作用。

这个想法是,您永远不需要编写包含处理契约(Contract)违约的特定逻辑的程序。它们永远不会在正确的程序中发生,并在需要修复的代码中指示严重错误。这类似于应避免捕获ArgumentNullException的方式。

在特殊情况下,您仍应抛出常规异常,这些异常并不表示代码本身存在错误,例如找不到文件时。这使调用代码可以适当地处理这种情况。



最好,在使用该软件之前,应该对其进行尽可能多的测试,以确保它从未违反任何契约(Contract)。

如果您有特定的需要重写运行时行为,则可以通过编写自己的契约(Contract)运行时类来实现。有关更多信息,请参见第7.7节:提供user manual的自定义契约(Contract)运行时类。

编辑:针对以下评论...



前提条件是契约(Contract),用于定义何时允许调用方法,并由调用方在调用该方法时进行验证。运行时检查器将在调用代码中注入(inject)适当的检查,而不是方法本身。如果您有可用的静态检查器,则在您无法确保前提条件后再调用该方法时,它将向您指出。

根据您的情况,处理数据的内部方法应定义前提条件,说明它们允许的数据类型。当数据从您无法控制的外部来源传入时,您应该对其进行验证并以通常的方式进行处理。您不想为此使用代码契约。但是,例如,如果您忘记完全验证该数据,则在使用前提条件调用内部代码时,您将遇到违反契约(Contract)的情况。这表明您自己的代码中存在错误。

关于.net - System.Diagnostics.Contracts契约(Contract)的有用性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3424895/

10-13 08:00