这是自定义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
类似,当你甚至不应该尝试处理它。
现在 - 我是对的?也许我不了解一些基本原则或倾向于过度设计一切?
答案 0 :(得分:2)
即使使用代码约定,最好在发布代码中抛出特定的异常,例如:
Contract.Requires<ArgumentNullException>(...);
首先:在您的发布/生产代码中,您不希望向用户显示断言窗口。
替代方案是抛出一个ContractException ,但是这个异常不能被“捕获”,因为它被声明为内部。
允许代码调用者优雅地处理某些异常的唯一选择(例如:像用户的无效输入)是抛出他可以捕获的异常。
Code Contracts的一大优势是,调用者实际上可以看到你将抛出的异常(通过sandcastle自动文档,* .Contracts.dlls,插件和工具......)并防范这些异常例外。如果没有代码合同,他必须依赖(可能已过时的)XML文档,甚至根本不需要。
答案 1 :(得分:1)
我尝试了Contract.Requires
和Exceptions
。我希望得到一个例外,明确告诉我,我滥用方法。
例外情况应该用于特殊事情。在向方法提供意外参数时就是这种情况。他们在那里告诉你,发生了一些意想不到的事情。
答案 2 :(得分:0)
这是一个用来检查前置条件的习惯用语。在java中你有Assertions,但是它们可以在运行时被停用...异常不是这样,它们提供了比断言“更强大”的合同验证(但是以牺牲一些运行时开销为代价)。
答案 3 :(得分:0)
这可能是因为抛出不同的异常会提供更多信息
为什么对ToBase64String
的调用失败了。例如,如果inArray
无效,则会显示一条消息
指示inArray
有效,以及异常类型。许多此类错误对您有用
调试问题调用ToBase64String并不打算被应用程序捕获。
仅使用Contract.Requires
之类的内容并不能提供太多信息。
答案 4 :(得分:0)
代码契约支持if-then-throw方法,可以更轻松地将合同添加到现有代码中。