代码契约:IEnumerator <t> .GetEnumerator()奇怪的继承契约?</t>

时间:2011-01-05 10:18:21

标签: c# visual-studio-2010 ienumerable code-contracts

我正在使用Code ContractsCode Contracts Editor Extensions VS2010加载项。我有一个实现IEnumerable<T>接口的类,我已经为GetEnumerator()方法实现了一个迭代器块。在它上面,我可以看到以下继承的合同:

ensures result != null    ensures result.Model == ((IEnumerable)this).Model    [Pure]    public IEnumerator(of IBaseMessage) GetEnumerator()    {

我理解第一个和第三个合同要求 - GetEnumerator()必须永远不会返回null,并且绝不能导致副作用。但第二份合同要求意味着什么? ModelIEnumerator<T>的{​​{1}}属性是什么?

编辑:正如Damien_The_Unbeliever在评论中指出的那样,IEnumerableIEnumerable<T>的合同位于单独的文件中,即合同参考大会。使用Reflector,在这两个接口的合同的反汇编中(完整代码为here),您可以看到以下内容:

IEnumerator<T>

有趣的是,[return: Fresh] [Escapes(true, false), Pure, GlobalAccess(false)] public IEnumerator GetEnumerator() { IEnumerator enumerator; Contract.Ensures((bool) (Contract.Result<IEnumerator>() != null), null, "Contract.Result<IEnumerator>() != null"); Contract.Ensures((bool) (Contract.Result<IEnumerator>().Model == this.Model), null, "Contract.Result<IEnumerator>().Model == this.Model"); Contract.Ensures((bool) (Contract.Result<IEnumerator>().CurrentIndex == -1), null, "Contract.Result<IEnumerator>().CurrentIndex == -1"); return enumerator; } 中的额外合同未被编辑扩展显示:

GetEnumerator()

还有一些额外的谜团(例如Contract.Result<IEnumerator>().CurrentIndex == -1 FreshEscapes属性。)

1 个答案:

答案 0 :(得分:2)

再看一下从C:\ Program Files \ Microsoft \ Contracts \ Contracts.NETFramework \ v4.0 \ mscorlib.Contracts.dll(在我的评论中引用)加载的代码/合约。

我相信您的实施可以安全地忽略它。它似乎与之相关的是它试图定义一个契约,以便(有效地)一旦你使用IEnumerator对象进行迭代,它将返回一定数量的元素。当对GetEnumerator的调用返回时,这些元素被有效地“快照”,并且对Reset和MoveNext的调用只能迭代同一组元素。

我认为它试图提供一些不变性保证。我不知道我们是否可以自己编写这些类似的合同 - 它使用ContractModel属性,这个属性似乎没有在任何地方记录,只要我能找到。


关于不可变性等:

我主要在返回的IEnumerator对象上查看MoveNext的合约 - 基本上,它说MoveNxt不能改变Model属性(我们知道GetEnumerator为它分配了相同的Model),以及CurrentIndex属性在0和Model.Length之间变化。在那之后,这只是直觉/猜测。我无法指出合同装配中的任何其他内容,它可以为我提供更多信息。