【问题标题】:Contract statements and assertions合同声明和断言
【发布时间】:2011-11-28 01:36:43
【问题描述】:

这是来自自定义 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 "";
        // ....
    }

检查此方法的先决条件(代码合同) 的语句不应该实际上是 assert-like 的吗? 我的意思是,抛出异常的意识形态在哪里? for code contract 违规从何而来?

下面的代码我很容易理解:

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

但是抛出不同的异常...... 为什么?

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

现在 - 我说得对吗?也许我不了解一些基本原理或倾向于过度设计所有内容?

【问题讨论】:

    标签: c# java exception code-contracts


    【解决方案1】:

    即使使用代码契约,最好在发布代码中抛出特定异常,如下所示:

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

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

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

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

    Code Contracts 的一大优势是调用者实际上可以看到您将抛出的异常(通过沙堡自动文档、*.Contracts.dll、插件和工具...)并保护自己免受这些异常的影响.如果没有代码合同,他将不得不依赖(可能已经过时的)XML 文档,甚至什么都不依赖。

    【讨论】:

      【解决方案2】:

      我试过Contract.RequiresExceptions。我更喜欢明确告诉我我滥用一种方法的异常。

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

      【讨论】:

        【解决方案3】:

        这是检查前置条件的常用习语。在 java 中,您有断言,但它们可以在运行时停用......异常不会,因此它们提供比断言“更强大”的合同验证(但会以一些运行时开销为代价)。

        【讨论】:

          【解决方案4】:

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

          仅使用 Contract.Requires 或类似名称并不能提供太多信息。

          【讨论】:

            【解决方案5】:

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

            【讨论】:

              猜你喜欢
              • 2012-12-11
              • 2014-04-09
              • 1970-01-01
              • 1970-01-01
              • 2019-08-09
              • 2022-11-03
              • 2020-04-12
              • 1970-01-01
              • 2015-10-27
              相关资源
              最近更新 更多