public KeyValueCollection(IReadOnlyCollection <KeyValuePair <TKey, TObject> > items, IComparer <KeyValuePair <TKey, TObject> > comparer, SortReason sortReason, SortOptimisations optimisations) { _items = items ?? throw new ArgumentNullException(nameof(items)); Comparer = comparer; SortReason = sortReason; Optimisations = optimisations; }
public KeyValueCollection(IEnumerable<KeyValuePair<TKey, TObject>> items, IComparer<KeyValuePair<TKey, TObject>> comparer, SortReason sortReason, SortOptimisations optimisations) { if (items == null) throw new ArgumentNullException(nameof(items)); _items = items.ToList(); Comparer = comparer; SortReason = sortReason; Optimisations = optimisations; }
/// <summary> /// Sorts using the specified sorter. Will return null if there are no changes /// </summary> /// <param name="sortReason">The sort reason.</param> /// <param name="changes">The changes.</param> /// <returns></returns> private ISortedChangeSet <TObject, TKey> DoSort(SortReason sortReason, IChangeSet <TObject, TKey> changes = null) { if (changes != null) { _cache.Clone(changes); changes = _cache.CaptureChanges(); _haveReceivedData = true; if (_comparer == null) { return(null); } } //if the comparer is not set, return nothing if (_comparer == null || !_haveReceivedData) { return(null); } if (!_initialised) { sortReason = SortReason.InitialLoad; _initialised = true; } else if (changes != null && (_resetThreshold > 0 && changes.Count >= _resetThreshold)) { sortReason = SortReason.Reset; } IChangeSet <TObject, TKey> changeSet; switch (sortReason) { case SortReason.InitialLoad: { //For the first batch, changes may have arrived before the comparer was set. //therefore infer the first batch of changes from the cache _calculator = new IndexCalculator <TObject, TKey>(_comparer, _optimisations); changeSet = _calculator.Load(_cache); } break; case SortReason.Reset: { _calculator.Reset(_cache); changeSet = changes; } break; case SortReason.DataChanged: { changeSet = _calculator.Calculate(changes); } break; case SortReason.ComparerChanged: { changeSet = _calculator.ChangeComparer(_comparer); if (_resetThreshold > 0 && _cache.Count >= _resetThreshold) { sortReason = SortReason.Reset; _calculator.Reset(_cache); } else { sortReason = SortReason.Reorder; changeSet = _calculator.Reorder(); } } break; case SortReason.Reorder: { changeSet = _calculator.Reorder(); } break; default: throw new ArgumentOutOfRangeException(nameof(sortReason)); } Debug.Assert(changeSet != null, "changeSet != null"); if ((sortReason == SortReason.InitialLoad || sortReason == SortReason.DataChanged) && changeSet.Count == 0) { return(null); } if (sortReason == SortReason.Reorder && changeSet.Count == 0) { return(null); } _sorted = new KeyValueCollection <TObject, TKey>((IReadOnlyCollection <KeyValuePair <TKey, TObject> >)_calculator.List, _comparer, sortReason, _optimisations); return(new SortedChangeSet <TObject, TKey>(_sorted, changeSet)); }
/// <summary> /// Sorts using the specified sorter. Will return null if there are no changes. /// </summary> /// <param name="sortReason">The sort reason.</param> /// <param name="changes">The changes.</param> /// <returns>The sorted change set.</returns> private ISortedChangeSet <TObject, TKey>?DoSort(SortReason sortReason, IChangeSet <TObject, TKey>?changes = null) { if (changes is not null) { _cache.Clone(changes); changes = _cache.CaptureChanges(); _haveReceivedData = true; } // if the comparer is not set, return nothing if (!_haveReceivedData) { return(null); } if (!_initialised) { sortReason = SortReason.InitialLoad; _initialised = true; } else if (changes is not null && (_resetThreshold > 0 && changes.Count >= _resetThreshold)) { sortReason = SortReason.Reset; } IChangeSet <TObject, TKey>?changeSet; switch (sortReason) { case SortReason.InitialLoad: { // For the first batch, changes may have arrived before the comparer was set. // therefore infer the first batch of changes from the cache _calculator = new IndexCalculator <TObject, TKey>(_comparer, _optimisations); changeSet = _calculator.Load(_cache); } break; case SortReason.Reset: { if (_calculator is null) { throw new InvalidOperationException("The calculator has not been initialized"); } _calculator?.Reset(_cache); changeSet = changes; } break; case SortReason.DataChanged: { if (_calculator is null) { throw new InvalidOperationException("The calculator has not been initialized"); } if (changes is null) { throw new InvalidOperationException("Data has been indicated as changed, but changes is null."); } changeSet = _calculator.Calculate(changes); } break; case SortReason.ComparerChanged: { if (_calculator is null) { throw new InvalidOperationException("The calculator has not been initialized"); } changeSet = _calculator.ChangeComparer(_comparer); if (_resetThreshold > 0 && _cache.Count >= _resetThreshold) { sortReason = SortReason.Reset; _calculator.Reset(_cache); } else { sortReason = SortReason.Reorder; changeSet = _calculator.Reorder(); } } break; case SortReason.Reorder: { if (_calculator is null) { throw new InvalidOperationException("The calculator has not been initialized"); } changeSet = _calculator.Reorder(); } break; default: throw new ArgumentOutOfRangeException(nameof(sortReason)); } if (changeSet is null) { throw new InvalidOperationException("Change set must not be null."); } if (_calculator is null) { throw new InvalidOperationException("The calculator has not been initialized"); } if ((sortReason == SortReason.InitialLoad || sortReason == SortReason.DataChanged) && changeSet.Count == 0) { return(null); } if (sortReason == SortReason.Reorder && changeSet.Count == 0) { return(null); } _sorted = new KeyValueCollection <TObject, TKey>(_calculator.List.ToList(), _comparer, sortReason, _optimisations); return(new SortedChangeSet <TObject, TKey>(_sorted, changeSet)); }