Как сообщить статической проверке, что свойство никогда не изменяется, если оно недоказуемо?

У моего класса есть свойство, которое инициализируется в конструкторе и не должно изменяться. Все методы в моей кодовой базе принимают этот класс в качестве параметра и полагаются на это свойство, удовлетворяющее определенному условию.

Ключевым моментом является то, что действительно недоказуемо, что свойство никогда не изменяется. Я могу лично «поклясться», что он никогда не меняется (и у меня есть модульные тесты для этого тоже), но это нельзя доказать формально (или, по крайней мере, я так думаю).

Рассмотрим следующий сокращенный пример:

    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 , так что он больше не будет удовлетворять условию.

Исходя из этого, я может вывести два возможных обходных пути, ни один из которых я считаю приемлемым:

  1. Добавить Contract.Ensures (c.SomeProp == Contract.OldValue (c.SomeProp)) в Метод , а также для любого другого метода, который принимает аргументы типа SomeClass .
    Легко понять, насколько это абсурдно.

  2. Добавьте избыточную проверку для c.SomeProp == 5 перед вторым вызовом метода (c) .
    Хотя это менее нелепо, чем первый вариант, он также неприемлем, поскольку помимо загромождения кода он также будет иметь снижение производительности (такая проверка не будет оптимизирована).

Идеальным решением было бы как-нибудь убедить контролера, что SomeProp не должен изменяться после построения, но я не мог найти никакого способа сделать это.

Или, может быть, я упускаю что-то очевидное?

1
задан Fyodor Soikin 21 October 2010 в 18:44
поделиться