/// <summary> /// Remove all items *not* in a supplied collection from this set. /// </summary> /// <param name="items">The items to retain</param> public virtual void RetainAll(SCG.IEnumerable <T> items) { updatecheck(); HashSet <T> aux = new HashSet <T>(EqualityComparer); //This only works for sets: foreach (var item in items) { if (Contains(item)) { T jtem = item; aux.searchoradd(ref jtem, true, false, false); } } if (size == aux.size) { return; } CircularQueue <T> wasRemoved = null; if ((ActiveEvents & EventTypeEnum.Removed) != 0) { wasRemoved = new CircularQueue <T>(); foreach (T item in this) { if (!aux.Contains(item)) { wasRemoved.Enqueue(item); } } } table = aux.table; size = aux.size; indexmask = aux.indexmask; resizethreshhold = aux.resizethreshhold; bits = aux.bits; bitsc = aux.bitsc; _randomhashfactor = aux._randomhashfactor; if ((ActiveEvents & EventTypeEnum.Removed) != 0) { raiseForRemoveAll(wasRemoved); } else if ((ActiveEvents & EventTypeEnum.Changed) != 0) { raiseCollectionChanged(); } }
/// <summary> /// /// </summary> /// <param name="item"></param> public void Remove(T item) { if (mustFireRemoved) { if (wasRemoved == null) { wasRemoved = new CircularQueue <T>(); } wasRemoved.Enqueue(item); } if (!wasChanged) { wasChanged = true; } }
/// <summary> /// Add the elements from another collection with a more specialized item type /// to this collection. /// </summary> /// <param name="items">The items to add</param> public virtual void AddAll(SCG.IEnumerable <T> items) { UpdateCheck(); #warning We could easily raise bag events bool mustRaiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0; CircularQueue <T>?wasAdded = mustRaiseAdded ? new CircularQueue <T>() : null; bool wasChanged = false; foreach (T item in items) { T jtem = item; Add(ref jtem); wasChanged = true; if (mustRaiseAdded) { wasAdded?.Enqueue(jtem); } } if (!wasChanged) { return; } if (mustRaiseAdded) { if (wasAdded != null) { foreach (T item in wasAdded) { RaiseItemsAdded(item, 1); } } } if ((ActiveEvents & EventTypeEnum.Changed) != 0) { RaiseCollectionChanged(); } }
/// <summary> /// Add the elements from another collection with a more specialized item type /// to this collection. Since this /// collection has set semantics, only items not already in the collection /// will be added. /// </summary> /// <param name="items">The items to add</param> public virtual void AddAll(SCG.IEnumerable <T> items) { UpdateCheck(); bool wasChanged = false; bool raiseAdded = (ActiveEvents & EventType.Added) != 0; CircularQueue <T> wasAdded = raiseAdded ? new CircularQueue <T>() : null; foreach (T item in items) { T jtem = item; if (!SearchOrAdd(ref jtem, true, false, false)) { wasChanged = true; if (raiseAdded) { wasAdded?.Enqueue(item); } } } //TODO: implement a RaiseForAddAll() method if (raiseAdded & wasChanged) { if (wasAdded != null) { foreach (T item in wasAdded) { RaiseItemsAdded(item, 1); } } } if (((ActiveEvents & EventType.Changed) != 0 && wasChanged)) { RaiseCollectionChanged(); } }
/// <summary> /// Remove all items *not* in a supplied collection from this bag, /// counting multiplicities. /// </summary> /// <param name="items">The items to retain</param> public virtual void RetainAll(SCG.IEnumerable <T> items) { updatecheck(); HashBag <T> res = new HashBag <T>(itemequalityComparer); foreach (T item in items) { KeyValuePair <T, int> p = new KeyValuePair <T, int>(item); if (dict.Find(ref p)) { KeyValuePair <T, int> q = p; if (res.dict.Find(ref q)) { if (q.Value < p.Value) { q.Value++; res.dict.Update(q); res.size++; } } else { q.Value = 1; res.dict.Add(q); res.size++; } } } if (size == res.size) { return; } CircularQueue <T> wasRemoved = null; if ((ActiveEvents & EventTypeEnum.Removed) != 0) { wasRemoved = new CircularQueue <T>(); foreach (KeyValuePair <T, int> p in dict) { int removed = p.Value - res.ContainsCount(p.Key); if (removed > 0) #warning We could send bag events here easily using a CircularQueue of (should?) { for (int i = 0; i < removed; i++) { wasRemoved.Enqueue(p.Key); } } } } dict = res.dict; size = res.size; if ((ActiveEvents & EventTypeEnum.Removed) != 0) { raiseForRemoveAll(wasRemoved); } else if ((ActiveEvents & EventTypeEnum.Changed) != 0) { raiseCollectionChanged(); } }
public virtual void RetainAll <U>(SCG.IEnumerable <U> items) where U : T { updatecheck(); HashBag <T> res = new HashBag <T>(ItemEqualityComparer); foreach (U item in items) { Multiplicity <T> p = new Multiplicity <T>(item); if (dict.Find(ref p)) { Multiplicity <T> q = p; if (res.dict.Find(ref q)) { if (q.Count < p.Count) { q.Count++; res.dict.Update(q); res.Size++; } } else { q.Count = 1; res.dict.Add(q); res.Size++; } } } if (Size == res.Size) { return; } CircularQueue <T> wasRemoved = null; if ((ActiveEvents & EventTypeEnum.Removed) != 0) { wasRemoved = new CircularQueue <T>(); foreach (Multiplicity <T> p in dict) { int removed = p.Count - res.ContainsCount(p.Value); if (removed > 0) #warning We could send bag events here easily using a CircularQueue of (should?) { for (int i = 0; i < removed; i++) { wasRemoved.Enqueue(p.Value); } } } } dict = res.dict; Size = res.Size; if ((ActiveEvents & EventTypeEnum.Removed) != 0) { raiseForRemoveAll(wasRemoved); } else if ((ActiveEvents & EventTypeEnum.Changed) != 0) { raiseCollectionChanged(); } }