按合同设计:您是否可以使用协议接口?

时间:2009-07-31 21:50:29

标签: c# .net design-by-contract microsoft-contracts

我对契约式设计的概念很陌生,但到目前为止,我很想知道找到潜在错误的难易程度。

但是,我一直在使用Microsoft.Contracts库(这非常棒),而且我遇到了障碍。

以我想要做的简化为例:

public enum State { NotReady, Ready }

[ContractClass(typeof(IPluginContract))]
public interface IPlugin
{
    State State { get; }
    void Reset();
    void Prepare();
    void Run();
}

[ContractClassFor(typeof(IPlugin))]
public class IPluginContract : IPlugin
{
    State IPlugin.State { get { throw new NotImplementedException(); } }

    void IPlugin.Reset()
    {
        Contract.Ensures(((IPlugin)this).State == State.NotReady);
    }

    void IPlugin.Prepare()
    {
        Contract.Ensures(((IPlugin)this).State == State.Ready);
    }

    void IPlugin.Run()
    {
        Contract.Requires(((IPlugin)this).State == State.Ready);
    }
}

class MyAwesomePlugin : IPlugin
{
    private State state = State.NotReady;

    private int? number = null;

    State IPlugin.State
    {
        get { return this.state; }
    }

    void IPlugin.Reset()
    {
        this.number = null;
        this.state = State.NotReady;
    }

    void IPlugin.Prepare()
    {
        this.number = 10;
        this.state = State.Ready;
    }

    void IPlugin.Run()
    {
        Console.WriteLine("Number * 2 = " + (this.number * 2));
    }
}

总而言之,我正在声明一个插件接口,要求它们声明它们的状态,并限制在任何状态下可以调用的内容。

这适用于调用站点,用于静态和运行时验证。但我不断得到的警告是“合同:确保未经证实”ResetPrepare函数。

我尝试过使用Invariant s,但这并没有帮助证明Ensures约束。

任何有关如何通过界面证明的帮助都会有所帮助。

EDIT1:

当我将它添加到MyAwesomePlugin类时:

    [ContractInvariantMethod]
    protected void ObjectInvariant()
    {
        Contract.Invariant(((IPlugin)this).State == this.state);
    }

试图暗示作为IPlugin的状态与我的私有状态相同,我得到相同的警告,并且警告“private int?number = null”行无法证明不变量。

鉴于这是静态构造函数中的第一个可执行行,我可以看出它为什么这么说,但为什么不能证明Ensures

EDIT2

当我用State标记[ContractPublicPropertyName("State")]时,我收到一条错误消息,说“没有找到名为'State'且属于'MyNamespace.State'的公共字段/属性”

似乎这样可以让我更接近,但我不在那里。

1 个答案:

答案 0 :(得分:1)

使用此代码段,我有效地抑制了警告:

    void IPlugin.Reset()
    {
        this.number = null;
        this.state = State.NotReady;
        Contract.Assume(((IPlugin)this).State == this.state);
    }

这实际上回答了我的第一个问题,但问了一个新问题:为什么不存在不变的帮助证明了这一点?

我将发布一个新问题。