如何告诉代码合约一个指定为参数的委托是纯函数?

4
请看以下代码:

考虑下面的代码:

int SomeField;
void Foo([Pure] Func<int, object> getData)
{
    Contract.Requires(getData != null);
    Contract.Requires(getData(this.SomeField) != null);
}

我收到了以下警告:
检测到对 'System.Func'2<System.Int32,System.Object>.Invoke(System.Int32)' 方法的调用,该方法在 '....Foo(System.Func'2<System.Int32,System.Object>)' 的合同中没有使用 [Pure]
这个警告是很有道理的。但我仍然想在契约中调用委托而不会收到警告(假设我已经将警告转换为错误)。如何实现?
我尝试了像示例中所示的 Pure 属性,但那行不通。
我还想知道为什么可以在参数上指定 PureAttribute。如果参数的类型不是委托类型,则没有意义;即使是委托类型,它也不按照我期望的那样工作,正如我上面所述。
2个回答

1

使用当前的Code Contracts库实现这一点的方法是声明自己的委托类型,如下所示:

[Pure]
public delegate U PureFunc<in T, out U>(T thing);

我认为它不能在委托参数上工作的原因是一般情况下很难检查 :)


好的,那个方案可以解决问题,但是并不是很优雅,因为这需要在代码的其他部分进行委托转换,但好吧,可以接受。但问题是,当PureAttribute分配给一个方法或委托时,并没有检查是否纯净,假设它是纯净的。那么为什么我不能指定委托参数为纯净的呢? - JBSnorro
我认为区别在于声明某些内容是纯洁的,和要求它成为纯洁的。当你声明一个方法为Pure时,这是一个积极的选择,但仅仅因为参数是纯洁的而隐含地假设委托是纯洁的并不是很理想。在这种情况下,方法的用户甚至可能不知道参数是纯洁的,并且可能会传入一些会破坏方法的东西。通过这种方式,方法的用户需要说明“是的,我知道这必须是纯洁的”。 - porges

1

我不习惯使用合约框架,但从纯逻辑的角度来看,委托不能是纯粹的,因为它可以接受任何符合签名的方法。你无法保证所有适合该委托的方法都能遵守合约,因为只需要一个方法就可以打破合约。


好的,这也很有道理。显然,并非所有的委托都是纯粹的。这并不意味着有些不能是纯粹的,我认为应该有一种机制来指定。但这引出了第二个问题...我会编辑我的帖子。 - JBSnorro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接