当无法证明属性时,如何告诉静态检查器属性永远不会改变?
我的类有一个在构造函数中初始化的属性,并且永远不应该更改。我的代码库周围的方法都接受该类作为参数,并依赖于满足特定条件的该属性。
关键是属性永远不变确实无法证明。我个人可以“发誓”它永远不会改变(并且我也对其进行了单元测试),但它无法被正式证明(或者至少我认为如此)。
考虑以下简化示例:
public class ConstantPoperty
{
public class SomeClass
{
public int SomeProp {
get { return GetSomePropThroughUnprovableMechanism(); }
}
public SomeClass( int i )
{
SetSomePropThroughUnprovableMechanism( i );
}
}
public void Method( SomeClass c )
{
Contract.Requires( c != null );
Contract.Requires( c.SomeProp == 5 );
}
public void FalsePositive()
{
SomeClass c = new SomeClass( 5 );
if ( c.SomeProp != 5 ) return;
Method( c );
Method( c ); // unproven requires: c.SomeProp == 5
}
}
请注意,对 Method()
的第一次调用从检查器中获得了 OK,因为我在它之前检查了条件是否满足。
然而,第二次调用会收到一个未经证实的警告。我的猜测是,检查器假设第一次调用 Method(c)
可能会更改 c.SomeProp
,以便它将不再满足条件。
由此,我可以推断出两种可能的解决方法,但我认为这两种方法都不可接受:
Add
Contract.Ensures( c.SomeProp == Contract.OldValue( c.SomeProp ) )
to方法
,以及接受SomeClass
类型参数的所有其他方法。
人们很容易看出这是多么荒谬。在第二次调用
Method(c)
之前添加对c.SomeProp == 5
的冗余检查。
虽然这不像第一个选项那么荒谬,但它也是不可接受的,因为除了使代码变得混乱之外,它还会带来性能损失(这样的检查不会被优化掉)。
理想的解决方案是以某种方式说服检查器 SomeProp
在构造后永远不会改变,但我找不到任何方法来做到这一点。
或者也许我在这里遗漏了一些明显的东西?
My class has a property that is initialized in the constructor and is never supposed to change. Methods all around my codebase accept that class as a parameter and rely on that property satisfying a certain condition.
The key point is that it is really unprovable that the property never changes. I can personally "swear" that it never changes (and I have unit tests for it, too), but it cannot be proved formally (or at least I think so).
Consider the following reduced example:
public class ConstantPoperty
{
public class SomeClass
{
public int SomeProp {
get { return GetSomePropThroughUnprovableMechanism(); }
}
public SomeClass( int i )
{
SetSomePropThroughUnprovableMechanism( i );
}
}
public void Method( SomeClass c )
{
Contract.Requires( c != null );
Contract.Requires( c.SomeProp == 5 );
}
public void FalsePositive()
{
SomeClass c = new SomeClass( 5 );
if ( c.SomeProp != 5 ) return;
Method( c );
Method( c ); // unproven requires: c.SomeProp == 5
}
}
Note that the first call to Method()
get an OK from the checker, since I've checked right before it that the condition is satisfied.
The second call, however, gets an unproven warning. My guess is, the checker assumes that the first call to Method(c)
might change c.SomeProp
so that it will no longer satisfy the condition.
From this, I can deduce two possible workarounds, neither of which I consider acceptable:
Add
Contract.Ensures( c.SomeProp == Contract.OldValue( c.SomeProp ) )
toMethod
, as well as to every other method that accepts arguments of typeSomeClass
.
One can easily see how this is absolutely ridiculous.Add a redundant check for
c.SomeProp == 5
before the second call toMethod(c)
.
While this is less ridiculous than the first option, it is also unacceptable, because in addition to cluttering the code, it will also have a performance penalty (such a check will not be optimized away).
The ideal solution would be to somehow convince the checker that SomeProp
is never supposed to change after construction, but I couldn't find any way to do this.
Or maybe I am missing something obvious here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
像这样重写它:
Rewrite it like this: