合同声明和断言

发布于 2024-12-18 10:31:23 字数 1088 浏览 1 评论 0原文

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

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

正确处理这种异常是不可能的,因为它仅表明存在逻辑缺陷,此错误类似于 Java 中的未经检查的异常,而您甚至不应该尝试处理它。

- 我说得对吗?也许我不理解一些基本原则或者倾向于过度设计一切?

This is the code from custom Microsoft .NET runtime implementation and I have the following questions:

    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 "";
        // ....
    }

Shouldn't the statements, which check the prerequisities (code contract) for this method actually be assert-like? I mean, where did the ideology of throwing exceptions for code contract violations come from?

I could easily understand the following code:

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

But throwing different exceptions... Why?

It's impossible to handle this sort of exception correctly, because it merely indicates the logic flaw, this error is similiar to unchecked exception in Java, when you also shouldn't even attempt to handle it.

Now - am I right? Maybe I don't understand some underlying principles or tend to over-engineer everything?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一桥轻雨一伞开 2024-12-25 10:31:23

即使使用代码契约,最佳实践也是在发布代码中引发特定异常,如下所示:

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

首先:在发布/生产代码中,不想显示断言窗口强>给用户。

另一种方法是抛出 ContractException,但此异常无法“捕获”,因为它被声明为内部异常。

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

代码契约的一大优点是,调用者实际上可以看到您将抛出的异常(通过 sandcastle 自动文档、*.Contracts.dll、插件和工具……)并防范这些异常。如果没有代码契约,他就必须依赖(可能已经过时的)XML 文档,甚至什么都不依赖。

Even with Code Contracts, it's a best practice to throw specific exceptions in release code, like this:

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

First: In your release/production code, you don't want to show assert windows to the user.

The alternative to that is throwing a ContractException, but this exception cannot be 'catched' because it is declared internal.

The only alternative left to allow the caller of your code to handle some exceptions gracefully ( eg: like invalid input from a user) is to throw exceptions he can catch.

The big advantage to Code Contracts is that the caller can actually see the exceptions you will be throwing ( via sandcastle auto-documentation, the *.Contracts.dlls, plugins & tools, ... ) and guard himself against these exceptions. Without Code Contracts, he'd have to rely on a (probably dated) XML documentation or even nothing at all.

不知所踪 2024-12-25 10:31:23

我尝试过 Contract.RequiresExceptions 。我更喜欢得到一个清楚告诉我我滥用方法的异常。

异常应该用于特殊的事情。当向方法提供意外参数时就会出现这种情况。他们在那里告诉您发生了一些意想不到的事情。

I have tried Contract.Requires and Exceptions. I prefer to get an exception that clearly tells me that I am misusing a method.

Exceptions should be used for exceptional things. It is the case when an unexpected parameter is supplied to a method. They are there to tell you that some thing unexpected occurred.

臻嫒无言 2024-12-25 10:31:23

这是检查先决条件的常用习惯用法。在java中,你有断言,但它们可以在运行时被停用......异常则不然,因此它们提供了比断言“更强”的契约验证(尽管以一些运行时开销为代价)。

This is a much used idiom to check for pre conditions. In java you have Assertions, but they can be deactivated at runtime...exceptions don't so they provide a "stronger" contract validation than assertions (at the expense of some runtime overhead though).

凑诗 2024-12-25 10:31:23

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

仅使用 Contract.Requires 或类似内容并不能提供那么多信息。

That's probably because throwing distinct exceptions gives more information about
why the call to ToBase64String failed. For example, if inArray is invalid, a message is displayed
indicating that inArray is valid, along with the kind of exception. Many such errors are useful for
debugging problems calling ToBase64String and are not meant to be caught by applications.

Using just Contract.Requires or the like doesn't give that much information.

纵山崖 2024-12-25 10:31:23

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

Code contracts supports the if-then-throw approach to make it easier to add contracts to existing code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文