C#的未来:方法契约(2)

我当然会使用快速失败,但我只想在我私人的工作中使用它,在公共项目中我还是希望使用异常。如果调用我代码的用户决定用大量的异常去喂饱异常这个怪兽(即选择使用异常),那也是他们自己的选择,他们(同时也隐含了他们代码的用户)也需要为这一决定买单。

  HaloFour 对以下观点表示同意:

我更希望方法契约能够抛出异常(至少是对于 requires 语句来说),然后添加一个语言关键字断言,在某种条件未满足的情况下会快速失败。

  异常类型

  这条提议中比较容易接受的部分是 Argument 异常,编译器会将某个简单的 requires 语句转化为某个 ArgumentNullException 或 ArgumentOutOfRange 异常。如果 requires 语句检查的内容是对象的状态,那么它可以抛出一个 InvalidOperationException 异常。但如果该语句同时检查参数与对象状态呢?这种情况下要决定抛出何种异常会成为一个相当复杂的问题。

  另外一个问题在于 ObjectDisposedException,因为没有什么标准方式能够表现一个被回收的对象。因此只能采取一些宽松的约定,检查是否存在某个叫做_disposed 或m_IsDisposed 之类名称的布尔型字段。这一点的重要性在于,InvalidOperationException 异常一般来说能够通过改变对象状态的方式进行恢复,而 ObjectDisposedException 永远做不到这一点。

  另一方面,需要通过某种异常表示 ensures 语句出错。与 requires 语句不同,在 ensures 契约中的错误总是意味着在方法内部存在 bug。

  本地化

  假设我们采取了某种基于异常的方式,那么接下来的问题就是本地化了。对于基本的参数检查来说,编译器可以简单地生成包含英文文本的参数异常。但如果这些异常信息需要本地化为其它语言呢?如果选择使用简化的语法,就不会明确地抛出某个参数异常。这种情况下,或者需要通过某种渠道添加本地化的信息,或者不得不使用冗长的语法以显示本地化异常信息。

  枚举与契约

  目前为止所讨论的契约都是一种附加条件,而在 Fabian Schmied 所提出的提议中,编译器将允许省略那些绝对不会命中的 return 语句。

public string GetText (MyEnum myEnum) requires defined (myEnum) { switch (myEnum) { case One: return "Single"; case Two: return "Pair"; case Three: return "Triple"; } // 所有分支情况都已涵盖,因此即使省略了 return 语句也不会产生错误。 }

  英文原文:C# Futures: Method Contracts

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/5085edf2588fcd57b1ac2256239da2cf.html