Я пытаюсь понять, как контракты кода .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();
}
}
}
Когда я запускаю инструмент статического анализа Code Contract, он выводит предупреждение: 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
в реальном коде что-то происходит)?
o1
, которое происходит автоматически во время выполнения конструктора, достаточным доказательством, гарантирующим o1!=null. Гарантия — это постусловие, аlock
означает, что метод будет вызываться из нескольких потоков. - person Robert Harvey   schedule 22.04.2013this.o1 = new object()
наthis.o2 = new object()
, все в порядке. В этом случае он не может гарантировать ничего, чего нельзя было бы гарантировать в исходном случае, и он по-прежнему включает блокировку. ИRequires
должно быть достаточным доказательством того, чтоo1
не равно нулю в начале метода. - person Philip C   schedule 23.04.2013