Пример #1
0
        /// <summary>
        /// It is way to find needed block if we don't cache it yet. This method have O(n) complexity.
        /// In fact we just get last cached block and move next until we find block we need. Also we cache all new blocks until needed.
        /// </summary>
        /// <param name="index">Index to find information about block, which containes it.</param>
        /// <param name="searchBlockRange"><see cref="Range"/> to find index in it. It use to get better performance.</param>
        /// <returns>Information about block, which contain specified index.</returns>
        private BlockInfo LinearBlockInfo(int index, Range searchBlockRange)
        {
            lock (_locker)
            {
                Debug.Assert(index >= GetCachedElementCount());

                if (!_blockCollection.IsValidRange(searchBlockRange))
                {
                    throw new ArgumentOutOfRangeException("searchBlockRange");
                }

                //Move to start
                var startBlock = GetStartBlockInfoForLinear();
                if (startBlock.Compare(index) == 0)
                {
                    return(startBlock);
                }

                int commonStartIndex = startBlock.CommonStartIndex + startBlock.Count;

                Debug.Assert(startBlock.CommonStartIndex + startBlock.Count <= index);

                //Start block must be last cached block info
                Debug.Assert(startBlock.IndexOfBlock + 1 == _blocksInfoList.Count);

                //Add new blocks while we try to find needed block
                for (int i = startBlock.IndexOfBlock + 1; i < searchBlockRange.Index + searchBlockRange.Count; i++)
                {
                    var elementCount = _blockCollection[i].Count;
                    var newBlock     = new BlockInfo(i, commonStartIndex, elementCount);
                    _blocksInfoList.Add(newBlock);

                    //If there is needed block
                    if (index >= commonStartIndex && index < commonStartIndex + elementCount)
                    {
                        if (i + 1 == _blockCollection.Count)
                        {
                            _indexOfFirstChangedBlock = NoBlockChanges;
                        }
                        else
                        {
                            _indexOfFirstChangedBlock = i + 1;
                        }

                        return(newBlock);
                    }

                    commonStartIndex += elementCount;
                }

                throw new ArgumentOutOfRangeException("index");
            }
        }