合同声明和断言

时间:2011-11-28 01:36:43

标签: c# java exception code-contracts

这是自定义Microsoft .NET运行时实现的代码,我有以下问题:

    public static string ToBase64String(byte[] inArray, int offset, int length)
    {
        if (inArray == null) throw new ArgumentNullException("inArray");
        if (offset < 0) throw new ArgumentOutOfRangeException("offset");
        if (length < 0) throw new ArgumentOutOfRangeException("length");
        if (offset + length > inArray.Length)
            throw new ArgumentException("offset + length > inArray.Length");

        // Fast return for the zero length case, note that this scenario is
        // absolutely valid.
        if (length == 0) return "";
        // ....
    }

检查此方法的先决条件(代码合同)的语句实际上不应该断言吗?我的意思是,抛出异常的意识形态在哪里?代码合同违规来自哪里?

我可以轻松理解以下代码:

Contract.Requires(inArray != null);
Contract.Requires(offset >= 0);
// ...

抛出不同的例外...... 为什么?

正确处理这种异常是不可能的,因为它只是表明了逻辑缺陷,这个错误与unchecked exception中的Java类似,当你甚至不应该尝试处理它。

现在 - 我是对的?也许我不了解一些基本原则或倾向于过度设计一切?

5 个答案:

答案 0 :(得分:2)

即使使用代码约定,最好在发布代码中抛出特定的异常,例如:

Contract.Requires<ArgumentNullException>(...);

首先:在您的发布/生产代码中,您不希望向用户显示断言窗口

替代方案是抛出一个ContractException ,但是这个异常不能被“捕获”,因为它被声明为内部。

允许代码调用者优雅地处理某些异常的唯一选择(例如:像用户的无效输入)是抛出他可以捕获的异常

Code Contracts的一大优势是,调用者实际上可以看到你将抛出的异常(通过sandcastle自动文档,* .Contracts.dlls,插件和工具......)并防范这些异常例外。如果没有代码合同,他必须依赖(可能已过时的)XML文档,甚至根本不需要。

答案 1 :(得分:1)

我尝试了Contract.RequiresExceptions。我希望得到一个例外,明确告诉我,我滥用方法。

例外情况应该用于特殊事情。在向方法提供意外参数时就是这种情况。他们在那里告诉你,发生了一些意想不到的事情。

答案 2 :(得分:0)

这是一个用来检查前置条件的习惯用语。在java中你有Assertions,但是它们可以在运行时被停用...异常不是这样,它们提供了比断言“更强大”的合同验证(但是以牺牲一些运行时开销为代价)。

答案 3 :(得分:0)

这可能是因为抛出不同的异常会提供更多信息 为什么对ToBase64String的调用失败了。例如,如果inArray无效,则会显示一条消息   指示inArray有效,以及异常类型。许多此类错误对您有用     调试问题调用ToBase64String并不打算被应用程序捕获。

仅使用Contract.Requires之类的内容并不能提供太多信息。

答案 4 :(得分:0)

代码契约支持if-then-throw方法,可以更轻松地将合同添加到现有代码中。