我正在尝试使用以下示例来研究.NET代码约定如何与lock
关键字进行交互:
public class TestClass
{
private object o1 = new object();
private object o2 = new object();
private void Test()
{
Contract.Requires(this.o1 != null);
Contract.Requires(this.o2 != null);
Contract.Ensures(this.o1 != null);
lock (this.o2) {
this.o1 = new object();
}
}
}
当我运行代码契约静态分析工具时,它会输出一个警告:Ensures unproven: this.o1 != null
如果我做了以下任何一项:
o2
中的lock
更改为o1
,o1
块内的lock
更改为o2
,lock
块中添加第二行,将new
object
分配给o2
lock (this.o2)
更改为if (this.o2 != null)
,lock
语句。但是,将lock
块中的行更改为var temp = new object();
(从而从方法中删除对o1
的所有引用)仍会导致警告:
private void Test()
{
Contract.Requires(this.o1 != null);
Contract.Requires(this.o2 != null);
Contract.Ensures(this.o1 != null);
lock (this.o2) {
var temp = new object();
}
}
所以有两个问题:
lock
内部确实发生了什么事情?)答案 0 :(得分:2)
以下是静态检查器如何处理锁和不变量:
如果使用表单lock(x.foo){...}锁定某些内容,静态检查程序会将x.foo视为x的保护锁。在锁定范围的最后,它假定其他线程可能访问x并对其进行修改。因此,静态检查器假定x的所有字段仅满足锁定范围之后的对象不变量,仅此而已。
请注意,这不是考虑所有线程交错,只是在锁定范围结束时进行交错。
答案 1 :(得分:1)
将以下代码添加到您的班级:
[ContractInvariantMethod]
private void ObjectInvariants()
{
Contract.Invariant(o1 != null);
}
我无法告诉您原因,但在这种情况下,静态验证程序似乎确实考虑了私有字段分配,并且缺少修改它的方法,作为该字段不会被修改的充分证据。它可能是验证者中的错误?可能值得报道Code Contracts forum。