Опитвам се да разбера как .NET Code Contracts взаимодействат с ключовата дума 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. Ensures е постусловие иlock
предполага, че методът ще бъде извикан от множество нишки. - person Robert Harvey   schedule 22.04.2013this.o1 = new object()
вthis.o2 = new object()
, всичко е наред. Не може да гарантира нищо в този случай, което не може да бъде гарантирано и в оригиналния случай, и все още включва заключване. ИRequires
трябва да е достатъчно доказателство, чеo1
не е нула в началото на метода. - person Philip C   schedule 23.04.2013