2013-02-20 53 views
17

我不知道我是否应该抛出异常,或致电Contract.Requires<TException>抛出异常vs合同。需要<T>?

例如:

public static void Function(String str) 
{ 
    if (str == null) throw new ArgumentNullException("str", "Input string cannot be null."); 

    // ... 
} 

VS

public static void Function(String str) 
{ 
    Contract.Requires<ArgumentNullException>(str != null, "Input string cannot be null."); 

    // ... 
} 

由于Contract.Requires<TException>不需要CONTRACTS_FULL符号,我可以把它放在我的发布版本也是如此。

这是我的考虑:

缺点:不能调用自定义异常类型的构造函数的重载版本。根本没有办法将其他参数传递给构造函数。

专业版:静态工具支持(例如通知调用者违反合同)。

我应该使用哪一个,以及是哪种情况?

+0

“重载异常类型构造函数”有什么好处? – 2013-03-01 14:58:35

+3

@PeterRitchie我认为这些构造函数存在的原因相同。我猜是因为它提供了更多的数据/信息。 – MasterMastic 2013-03-01 15:04:10

+1

我不明白你有关重载异常类型的问题。另外,您可能误解了Contract.Requires 的用法。如果使用过载,您仍然需要在释放的位上使用这些工具。如果不使用CodeContract工具重写DLL,它不会达到您的期望。 – 2013-04-26 22:13:29

回答

7

CodeContract用户指南中介绍的if-then-throw和​​之间的基本取舍是如何使用您的发布位进行构建。

案例1:您只能使用if-then-throw,否​​。在这种情况下,您可以构建您的版本位而无需在您的dll/exe上运行合约工具。优点是您的构建速度更快,并且不存在该工具引入错误的风险。第二个好处是团队成员可以选择不使用CodeContract工具。缺点是您不需要合同继承,您的合同不一定对工具可见(除非您使用EndContract)。您可以使用汇编模式指定此案例:自定义参数验证

案例2:您决定始终在发布位上运行CodeContract工具。这使您可以使用​​,并且您可以获得合同的继承,包括接口的检测等。您的合同是干净的并且是工具可识别的。缺点是每个构建代码的人都必须安装CodeContracts工具。您可以使用装配模式指定此案例:“合同”属性窗格中的“标准”。

希望这个清楚的事情。

+0

使用VS2017,有一个破解CodeContracts工具的工作 [VS2017是否与CodeContracts一起工作?](// stackoverflow.com/q/40767941) – 2017-09-03 06:01:15

2

我不知道,有两种方法之间的任何惊天动地的差异,但这里有两个原因我宁愿合同...

1)的代码是非常巧妙的,因为你写该方法顶部的陈述显示了该方法所基于的假设。如果假设被违反,您不会阻止代码的执行。

2)当您编写代码时,您可以从Visual Studio中获得代码合同的好处,并为您提供有关即将调用的方法的预期提示。这可以帮助您确保发送方法有效参数,而不必跳转到方法定义以检查那里的代码。

代码编译并运行后,我认为没有任何显着差异。

希望这会有所帮助。

+1

想要添加两个更多的优点。 Contracts.Requires可以使用构建符号轻松地“关闭”(当您确定检查通过时)。其次(我怀疑Avrohom不愿意)是VS有一个静态代码分析引擎,它可以被启用,它可以找到可能违反契约的CALLING代码的实例。 – Aron 2013-03-26 09:23:50