合同声明和断言
这是来自自定义 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
即使使用代码契约,最佳实践也是在发布代码中引发特定异常,如下所示:
首先:在发布/生产代码中,不想显示断言窗口强>给用户。
另一种方法是抛出 ContractException,但此异常无法“捕获”,因为它被声明为内部异常。
允许代码的调用者优雅地处理某些异常(例如:来自用户的无效输入)的唯一选择是抛出他可以捕获的异常。
代码契约的一大优点是,调用者实际上可以看到您将抛出的异常(通过 sandcastle 自动文档、*.Contracts.dll、插件和工具……)并防范这些异常。如果没有代码契约,他就必须依赖(可能已经过时的)XML 文档,甚至什么都不依赖。
Even with Code Contracts, it's a best practice to throw specific exceptions in release code, like this:
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.
我尝试过
Contract.Requires
和Exceptions
。我更喜欢得到一个清楚告诉我我滥用方法的异常。异常应该用于特殊的事情。当向方法提供意外参数时就会出现这种情况。他们在那里告诉您发生了一些意想不到的事情。
I have tried
Contract.Requires
andExceptions
. 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.
这是检查先决条件的常用习惯用法。在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).
这可能是因为抛出不同的异常可以提供更多信息
为什么调用
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, ifinArray
is invalid, a message is displayedindicating that
inArray
is valid, along with the kind of exception. Many such errors are useful fordebugging 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.代码契约支持 if-then- throw 方法,可以更轻松地将契约添加到现有代码中。
Code contracts supports the if-then-throw approach to make it easier to add contracts to existing code.