У моего класса есть свойство, которое инициализируется в конструкторе и не должно изменяться. Все методы в моей кодовой базе принимают этот класс в качестве параметра и полагаются на это свойство, удовлетворяющее определенному условию.
Ключевым моментом является то, что действительно недоказуемо, что свойство никогда не изменяется. Я могу лично «поклясться», что он никогда не меняется (и у меня есть модульные тесты для этого тоже), но это нельзя доказать формально (или, по крайней мере, я так думаю).
Рассмотрим следующий сокращенный пример:
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 ()
дает подтверждение от средства проверки, поскольку я проверил прямо перед этим, что условие выполняется.
У моего класса есть свойство, которое инициализируется в конструкторе и не должно изменяться. Все методы в моей кодовой базе принимают этот класс в качестве параметра и полагаются на это свойство, удовлетворяющее определенному условию.
Ключевым моментом является то, что действительно недоказуемо, что свойство никогда не изменяется. Я могу лично «поклясться», что он никогда не меняется (и у меня есть модульные тесты для этого тоже), но это нельзя доказать формально (или, по крайней мере, я так думаю).
Рассмотрим следующий сокращенный пример:
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 ()
дает подтверждение от средства проверки, поскольку я проверил прямо перед этим, что условие выполняется.
У моего класса есть свойство, которое инициализируется в конструкторе и не должно изменяться. Все методы в моей кодовой базе принимают этот класс в качестве параметра и полагаются на это свойство, удовлетворяющее определенному условию.
Ключевым моментом является то, что действительно недоказуемо, что свойство никогда не изменяется. Я могу лично «поклясться», что он никогда не меняется (и у меня есть модульные тесты для этого тоже), но это нельзя доказать формально (или, по крайней мере, я так думаю).
Рассмотрим следующий сокращенный пример:
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 ()
дает подтверждение от средства проверки, поскольку я проверил прямо перед этим, что условие выполняется.
Ключевым моментом является то, что на самом деле невозможно доказать, что свойство никогда не меняется. Я могу лично «поклясться», что он никогда не меняется (и у меня есть модульные тесты для этого тоже), но это нельзя доказать формально (или, по крайней мере, я так думаю).
Рассмотрим следующий сокращенный пример:
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 ()
дает подтверждение от средства проверки, поскольку я проверил прямо перед этим, что условие выполняется.
Ключевым моментом является то, что на самом деле невозможно доказать, что свойство никогда не меняется. Я могу лично «поклясться», что он никогда не меняется (и у меня есть модульные тесты для этого тоже), но это нельзя доказать формально (или, по крайней мере, я так думаю).
Рассмотрим следующий сокращенный пример:
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 ()
дает подтверждение от средства проверки, поскольку я проверил прямо перед этим, что условие выполняется.
Однако второй вызов получает недоказанное предупреждение. Я предполагаю, что программа проверки предполагает, что первый вызов метода (c)
может изменить c.SomeProp
, так что он больше не будет удовлетворять условию.
Исходя из этого, я может вывести два возможных обходных пути, ни один из которых я считаю приемлемым:
Добавить Contract.Ensures (c.SomeProp == Contract.OldValue (c.SomeProp))
в Метод
, а также для любого другого метода, который принимает аргументы типа SomeClass
.
Легко понять, насколько это абсурдно.
Добавьте избыточную проверку для c.SomeProp == 5
перед вторым вызовом метода (c)
.
Хотя это менее нелепо, чем первый вариант, он также неприемлем, поскольку помимо загромождения кода он также будет иметь снижение производительности (такая проверка не будет оптимизирована).
Идеальным решением было бы как-нибудь убедить контролера, что SomeProp
не должен изменяться после построения, но я не мог найти никакого способа сделать это.
Или, может быть, я упускаю что-то очевидное?