// Constructor. public Enumerator(ListRangeView <T> view) { this.view = view; this.index = view.startIndex - 1; }
public void Dispose() { this.view = null; }
/// <summary> /// Add elements to list. /// </summary> /// <param name="elements">Elements to add.</param> /// <param name="isSorted">Whether elements in <paramref name="elements"/> are already sorted or not.</param> public void AddAll(IEnumerable <T> elements, bool isSorted = false) { // sort elements var sortedElements = this.Sort(elements, isSorted); var elementCount = sortedElements.Count; if (elementCount <= 0) { return; } if (elementCount == 1) { this.Add(sortedElements[0]); return; } // insert to tail of list var list = this.list; var count = list.Count; var comparer = this.comparer; if (count == 0 || comparer.Compare(sortedElements[0], list[count - 1]) >= 0) { list.AddRange(sortedElements); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)sortedElements.AsReadOnly(), count)); return; } // insert to head of list if (comparer.Compare(sortedElements[elementCount - 1], list[0]) <= 0) { list.InsertRange(0, sortedElements); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)sortedElements.AsReadOnly(), 0)); return; } // find insertion position var insertStartIndex = list.BinarySearch(sortedElements[0], comparer); var insertEndIndex = list.BinarySearch(sortedElements[elementCount - 1], comparer); if (insertStartIndex < 0) { insertStartIndex = ~insertStartIndex; } if (insertEndIndex < 0) { insertEndIndex = ~insertEndIndex; } // insert to single position var insertionRegionSize = (insertEndIndex - insertStartIndex); if (insertionRegionSize < 0) { if (!this.IsSorted(comparer)) { throw new InternalStateCorruptedException(); } throw new ArgumentException("Elements are not sorted properly."); } if (insertionRegionSize == 0) { list.InsertRange(insertStartIndex, sortedElements); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)sortedElements.AsReadOnly(), insertStartIndex)); return; } // reserve space first if (list.Capacity < count + elementCount) { if (list.Capacity < int.MaxValue >> 1) { list.Capacity = Math.Max(count << 1, count + (elementCount << 1)); } else { list.Capacity = count + (elementCount << 1); } } // insert by blocks var seStartIndex = 0; var seIndex = 0; var insertionCount = 0; while (seIndex < elementCount && insertStartIndex < count) { var seElement = sortedElements[seIndex]; var comparisonResult = comparer.Compare(seElement, list[insertStartIndex]); if (comparisonResult <= 0) { ++seIndex; } else { insertionCount = (seIndex - seStartIndex); if (insertionCount == 1) { list.Insert(insertStartIndex, sortedElements[seStartIndex]); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, sortedElements[seStartIndex], insertStartIndex)); insertStartIndex += 2; ++count; } else if (insertionCount > 0) { var insertionElements = new ListRangeView <T>(sortedElements, seStartIndex, insertionCount); list.InsertRange(insertStartIndex, insertionElements); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, insertionElements, insertStartIndex)); insertStartIndex += insertionCount + 1; count += insertionCount; } else { ++insertStartIndex; } seStartIndex = seIndex; } } insertionCount = (elementCount - seStartIndex); if (insertionCount == 1) { list.Insert(insertStartIndex, sortedElements[seStartIndex]); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, sortedElements[seStartIndex], insertStartIndex)); } else if (insertionCount > 0) { var insertionElements = new ListRangeView <T>(sortedElements, seStartIndex, insertionCount); list.InsertRange(insertStartIndex, insertionElements); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, insertionElements, insertStartIndex)); } }