代码之家  ›  专栏  ›  技术社区  ›  roundcrisis

代码契约[Type]实现接口方法{interface.method},因此无法添加需求

  •  21
  • roundcrisis  · 技术社区  · 15 年前

    我有以下场景:

    public interface ISomething
    {
        void DoStuff();
        //...
    }
    
    public class Something : ISomething
    {
        private readonly ISomethingElse _somethingElse;
        //...
    
        public Something (ISomethingElse somethingElse)
        {
             Contract.Requires(somethingElse != null);
            _somethingElse = somethingElse;
        }
    
        public void DoStuff()
        {
            // *1* Please look at explanation / question below
            _somethingElse.DoThings();
        }
     }
    

    当静态检查器打开时,我会得到一个警告 _somethingElse

    [Type]实现接口方法{interface.method},因此无法添加需求

    在这里做什么最好?我看到的选项包括

    1. 一个保护条款,虽然它看起来是 有点极端
    2. Contract.Assume

    请注意字段是 readonly 因此,在构造函数中设置值之后,不可能更改。因此,代码契约发出的警告似乎 一点 无关紧要。

    1 回复  |  直到 14 年前
        1
  •  19
  •   Community Mohan Dere    5 年前

    解释

    第三节合同继承 user manual 声明必须在继承/实现链的根方法中定义所有前提条件:

    o 其静态类型为 T ,则客户端在调用 o.M o 有类型 U . 因此,该方法 U.M T.M .

    虽然我们可以允许一个较弱的先决条件,但我们发现这样做的复杂性大于好处。我们只是没有看到任何令人信服的例子,在那里削弱先决条件是有用的。所以我们不允许在子类型中添加任何前提条件。

    因此,必须在继承/实现链的根方法上声明方法前提条件,即第一个虚拟或抽象方法声明,或接口方法本身。

    解决方案

    在您的情况下,最好的做法是设置一个不变量,声明 _somethingElse 字段从不为空:

    [ContractInvariantMethod]
    private void ObjectInvariant() {
        Contract.Invariant(_somethingElse != null);
    }
    

    这当然总是正确的,因为字段被标记 readonly 并在构造函数中初始化。但是静态检查器本身无法推断出这一点,因此必须通过该不变量显式地告诉它。

    Contract.Ensures(_somethingElse != null); 但是静态检查器不需要它。