我对按合同设计的概念还很陌生,但到目前为止,我很喜欢它让查找潜在错误变得多么容易。
但是,我一直在使用 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));
}
}
总而言之,我声明了一个插件遵循的接口,并要求它们声明它们的状态,并限制在任何状态下可以调用的内容。
这适用于调用站点,用于静态和运行时验证。但我不断收到的警告是“合同:确保未经证实”的Reset
和Prepare
功能。
我曾尝试使用Invariant
s 进行处理,但这并不能帮助证明Ensures
约束。
关于如何通过界面证明的任何帮助都会有所帮助。
编辑1:
当我将此添加到 MyAwesomePlugin 类时:
[ContractInvariantMethod]
protected void ObjectInvariant()
{
Contract.Invariant(((IPlugin)this).State == this.state);
}
试图暗示作为 IPlugin 的状态与我的私有状态相同,我收到相同的警告,并且警告“私有 int?number = null”行无法证明不变量。
鉴于这是静态构造函数中的第一个可执行行,我可以理解为什么它会这样说,但为什么不能证明Ensures
?
编辑2
当我标记State
时,[ContractPublicPropertyName("State")]
我收到一条错误消息,提示“找不到名为 'State' 且类型为 'MyNamespace.State' 的公共字段/属性”
似乎这应该让我更接近,但我并不完全在那里。