Contract.Ensures和异常处理

时间:2013-10-18 15:10:53

标签: c# code-contracts

我最近发现了.NET Contracts API,虽然我不喜欢使用方法的实现方式而不喜欢扩展语法( Sing#在我看来做得对),我更喜欢使用它们而不是旧的/常规的方式使用if用于例如空检查。

我也正在接近我的第一个Contract.Ensures-calls,我偶然发现了一个问题,我们如何在包含Contract.Ensures的方法中处理异常,这些方法在运行时遭遇异常?

单词Contract。确保有点像我必须处理方法中的异常并让我的类再次进入正确的状态,但如果我不能做什么呢?

假设我们在这里有这个课程:

public class PluginManager
{
    private ILoadedFromAtCompileTimeUnknownAssembly extension;

    public bool IsFinished { get; private set; }

    public void Finish()
    {
        extension.Finish();
        this.IsFinished = true;
    }
}

我们可以使用Contract.Ensures来确保方法完成后IsFinished为真吗?

2 个答案:

答案 0 :(得分:2)

是。确保基本上意味着“确保方法是否正常终止”,即无例外。

答案 1 :(得分:1)

我发现很难让代码合同的概念正确。代码契约旨在发现编程错误。如果以这种方式应用,您可以删除发布版本的合同,您的应用程序将继续完美运行。

但很难区分编程(又称逻辑错误)与配置和输入数据问题。这些检查必须保留在您的发布版本中。因此,使用代码约定来检查扩展/插件是否正确加载是一个坏主意,因为它通常被配置到您的应用程序中。如果在发布版本中删除合同,则会因应用程序在调试版本或发布版本中配置错误而导致应用程序的行为不同。

报告的合同违规只有一种例外类型,这使得无法在应用程序的上层对例如应用程序中的配置问题或逻辑错误。有了反应,我不是要继续,而是向用户/开发人员提出一条远程有用的消息。

代码合同在表面看起来不错,但我担心大多数人会以错误的方式使用它。它并不是要在您的方法中替换所有null检查以进行输入验证。您应该仅使用与代码契约进行null检查的方法进行替换,其中您确定逻辑问题而不是输入数据是根本原因。

如果您希望自己的文件名是控制台应用程序作为输入,并且用户确实忘记在命令行提供文件名,使用ContracException迎接用户不是一个好主意。

  • 错误消息会让用户感到困惑。
  • 您不能将编程错误与用户输入验证问题区分开来。
  • 您无法捕获任何特定的ContractException,因为异常类型是内部的。

请参阅user documentation

  

7.6 ContractException ContractException类型不是公共类型,并作为嵌套的私有类型发布到每个程序集中   运行时合同检查已启用。因此不可能写   捕获处理程序只捕获ContractException。合同例外   因此只能作为一般异常支持的一部分来处理。该   这种设计的基本原理是程序不应包含控制权   依赖于合同失败的逻辑,就像程序不应该这样   catch ArgumentNullException或类似的验证异常。