代码之家  ›  专栏  ›  技术社区  ›  Dan Bryant

代码契约静态分析:验证程序限制?

  •  2
  • Dan Bryant  · 技术社区  · 14 年前

    public abstract class MemoryEncoder
    {
        private const int CapacityDelta = 16;
    
        private int _currentByte;
    
        /// <summary>
        ///   The current byte index in the encoding stream.
        ///   This should not need to be modified, under typical usage,
        ///   but can be used to randomly access the encoding region.
        /// </summary>
        public int CurrentByte
        {
            get
            {
                Contract.Ensures(Contract.Result<int>() >= 0);
                Contract.Ensures(Contract.Result<int>() <= Length);
                return _currentByte;
            }
            set
            {
                Contract.Requires(value >= 0);
                Contract.Requires(value <= Length);
                _currentByte = value;
            }
        }
    
        /// <summary>
        ///   Current number of bytes encoded in the buffer.
        ///   This may be less than the size of the buffer (capacity).
        /// </summary>
        public int Length { get; private set; }
    
        /// <summary>
        /// The raw buffer encapsulated by the encoder.
        /// </summary>
        protected internal Byte[] Buffer { get; private set; }
    
        /// <summary>
        /// Reserve space in the encoder buffer for the specified number of new bytes
        /// </summary>
        /// <param name="bytesRequired">The number of bytes required</param>
        protected void ReserveSpace(int bytesRequired)
        {
            Contract.Requires(bytesRequired > 0);
            Contract.Ensures((Length - CurrentByte) >= bytesRequired);
    
            //Check if these bytes would overflow the current buffer););
            if ((CurrentByte + bytesRequired) > Buffer.Length)
            {
                //Create a new buffer with at least enough space for the additional bytes required
                var newBuffer = new Byte[Buffer.Length + Math.Max(bytesRequired, CapacityDelta)];
    
                //Copy the contents of the previous buffer and replace the original buffer reference
                Buffer.CopyTo(newBuffer, 0);
                Buffer = newBuffer;
            }
    
            //Check if the total length of written bytes has increased
            if ((CurrentByte + bytesRequired) > Length)
            {
                Length = CurrentByte + bytesRequired;
            }
        }
    
        [ContractInvariantMethod]
        private void GlobalRules()
        {
            Contract.Invariant(Buffer != null);
            Contract.Invariant(Length <= Buffer.Length);
            Contract.Invariant(CurrentByte >= 0);
            Contract.Invariant(CurrentByte <= Length);
        }
    }
    

    1 回复  |  直到 14 年前
        1
  •  3
  •   Dan Bryant    14 年前

    public abstract class MemoryEncoder
    {
        private const int CapacityDelta = 16;
    
        private byte[] _buffer;
        private int _currentByte;
        private int _length;
    
        protected MemoryEncoder()
        {
            Buffer = new byte[500];
            Length = 0;
            CurrentByte = 0;
        }
    
        /// <summary>
        ///   The current byte index in the encoding stream.
        ///   This should not need to be modified, under typical usage,
        ///   but can be used to randomly access the encoding region.
        /// </summary>
        public int CurrentByte
        {
            get
            {
                return _currentByte;
            }
            set
            {
                Contract.Requires(value >= 0);
                Contract.Requires(value <= Length);
                _currentByte = value;
            }
        }
    
    
        /// <summary>
        ///   Current number of bytes encoded in the buffer.
        ///   This may be less than the size of the buffer (capacity).
        /// </summary>
        public int Length
        {
            get { return _length; }
            private set
            {
                Contract.Requires(value >= 0);
                Contract.Requires(value <= _buffer.Length);
                Contract.Requires(value >= CurrentByte);
                Contract.Ensures(_length <= _buffer.Length);
                _length = value;
            }
        }
    
        /// <summary>
        /// The raw buffer encapsulated by the encoder.
        /// </summary>
        protected internal Byte[] Buffer
        {
            get { return _buffer; }
            private set
            {
                Contract.Requires(value != null);
                Contract.Requires(value.Length >= _length);
                _buffer = value;
            }
        }
    
        /// <summary>
        /// Reserve space in the encoder buffer for the specified number of new bytes
        /// </summary>
        /// <param name="bytesRequired">The number of bytes required</param>
        protected void ReserveSpace(int bytesRequired)
        {
            Contract.Requires(bytesRequired > 0);
            Contract.Ensures((Length - CurrentByte) >= bytesRequired);
    
            //Check if these bytes would overflow the current buffer););
            if ((CurrentByte + bytesRequired) > Buffer.Length)
            {
                //Create a new buffer with at least enough space for the additional bytes required
                var newBuffer = new Byte[Buffer.Length + Math.Max(bytesRequired, CapacityDelta)];
    
                //Copy the contents of the previous buffer and replace the original buffer reference
                Buffer.CopyTo(newBuffer, 0);
                Buffer = newBuffer;
            }
    
            //Check if the total length of written bytes has increased
            if ((CurrentByte + bytesRequired) > Length)
            {
                Contract.Assume(CurrentByte + bytesRequired <= _buffer.Length);
                Length = CurrentByte + bytesRequired;
            }
        }
    
        [ContractInvariantMethod]
        private void GlobalRules()
        {
            Contract.Invariant(_buffer != null);
            Contract.Invariant(_length <= _buffer.Length);
            Contract.Invariant(_currentByte >= 0);
            Contract.Invariant(_currentByte <= _length);
        }
    }
    

    我注意到的主要一点是,在属性上放置不变量会变得混乱,但在字段上放置不变量似乎更容易解决问题。同样重要的是,对财产进入者规定适当的合同义务。我得继续试验,看看什么有效,什么无效。这是一个有趣的系统,但我肯定想知道更多,如果有人有一个很好的'备忘单'如何证明工作。