Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Collections/3.3/ObservableSet.cs @ 17718

Last change on this file since 17718 was 17718, checked in by abeham, 4 years ago

#2521: completed port of VRP (needs testing though)

File size: 8.4 KB
RevLine 
[2623]1#region License Information
2/* HeuristicLab
[17226]3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[2623]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections;
24using System.Collections.Generic;
25using System.ComponentModel;
26using System.Linq;
[16723]27using HEAL.Attic;
[2623]28
29namespace HeuristicLab.Collections {
[16723]30  [StorableType("44FF4DAE-F308-4B3B-8475-0B0327619657")]
[2623]31  [Serializable]
32  public class ObservableSet<T> : IObservableSet<T> {
[3560]33    [Storable]
[3286]34    protected HashSet<T> set;
[2623]35
36    #region Properties
37    public IEqualityComparer<T> Comparer {
38      get { return set.Comparer; }
39    }
40    public int Count {
41      get { return set.Count; }
42    }
43    bool ICollection<T>.IsReadOnly {
44      get { return ((ICollection<T>)set).IsReadOnly; }
45    }
46    #endregion
47
48    #region Constructors
49    public ObservableSet() {
50      set = new HashSet<T>();
51    }
52    public ObservableSet(IEnumerable<T> collection) {
53      set = new HashSet<T>(collection);
54    }
55    public ObservableSet(IEqualityComparer<T> comparer) {
56      set = new HashSet<T>(comparer);
57    }
58    public ObservableSet(IEnumerable<T> collection, IEqualityComparer<T> comparer) {
59      set = new HashSet<T>(collection, comparer);
60    }
[3560]61    [StorableConstructor]
[16723]62    protected ObservableSet(StorableConstructorFlag _) { }
[2623]63    #endregion
64
65    #region Access
66    public bool Contains(T item) {
67      return set.Contains(item);
68    }
69
70    public bool IsProperSubsetOf(IEnumerable<T> other) {
71      return set.IsProperSubsetOf(other);
72    }
73    public bool IsProperSupersetOf(IEnumerable<T> other) {
74      return set.IsProperSupersetOf(other);
75    }
76
77    public bool IsSubsetOf(IEnumerable<T> other) {
78      return set.IsSubsetOf(other);
79    }
80    public bool IsSupersetOf(IEnumerable<T> other) {
81      return set.IsSupersetOf(other);
82    }
83
84    public bool Overlaps(IEnumerable<T> other) {
85      return set.Overlaps(other);
86    }
87
88    public bool SetEquals(IEnumerable<T> other) {
89      return set.SetEquals(other);
90    }
91    #endregion
92
93    #region Manipulation
94    public bool Add(T item) {
95      if (set.Add(item)) {
96        OnPropertyChanged("Count");
97        OnItemsAdded(new T[] { item });
98        return true;
99      }
100      return false;
101    }
102    void ICollection<T>.Add(T item) {
103      Add(item);
104    }
105
106    public void ExceptWith(IEnumerable<T> other) {
107      if (other == null) throw new ArgumentNullException();
108      List<T> items = new List<T>();
109      foreach (T item in other) {
110        if (set.Remove(item))
111          items.Add(item);
112      }
113      if (items.Count > 0) {
114        OnPropertyChanged("Count");
115        OnItemsRemoved(items);
116      }
117    }
118
119    public void IntersectWith(IEnumerable<T> other) {
120      if (other == null) throw new ArgumentNullException();
121      HashSet<T> items = new HashSet<T>();
122      foreach (T item in set) {
123        if (!other.Contains(item)) items.Add(item);
124      }
125      if (items.Count > 0) {
126        set.ExceptWith(items);
127        OnPropertyChanged("Count");
128        OnItemsRemoved(items);
129      }
130    }
131
[17718]132    /// <summary>
133    /// Performs a Clear and an Add, but does not fire separate events for those operations
134    /// </summary>
135    /// <param name="other"></param>
136    public void Replace(IEnumerable<T> other) {
137      List<T> oldItems = null;
138      if (set.Any()) oldItems = new List<T>(set);
139      else oldItems = new List<T>();
140
141      set.Clear();
142      set.UnionWith(other);
143
144      List<T> items = null;
145      if (set.Any()) items = new List<T>(set);
146      else items = new List<T>();
147
148      OnCollectionReset(items, oldItems);
149      if (oldItems.Count != items.Count) OnPropertyChanged("Count");
150    }
151
[2623]152    public bool Remove(T item) {
153      if (set.Remove(item)) {
154        OnPropertyChanged("Count");
155        OnItemsRemoved(new T[] { item });
156        return true;
157      }
158      return false;
159    }
160    public int RemoveWhere(Predicate<T> match) {
161      if (match == null) throw new ArgumentNullException();
162      HashSet<T> items = new HashSet<T>();
163      foreach (T item in set) {
164        if (match(item)) items.Add(item);
165      }
166      if (items.Count > 0) {
167        set.ExceptWith(items);
168        OnPropertyChanged("Count");
169        OnItemsRemoved(items);
170      }
171      return items.Count;
172    }
173
174    public void SymmetricExceptWith(IEnumerable<T> other) {
175      if (other == null) throw new ArgumentNullException();
176      List<T> addedItems = new List<T>();
177      List<T> removedItems = new List<T>();
178      foreach (T item in other) {
179        if (set.Contains(item)) {
180          set.Remove(item);
181          removedItems.Add(item);
182        } else {
183          set.Add(item);
184          addedItems.Add(item);
185        }
186      }
187      if ((addedItems.Count > 0) || (removedItems.Count > 0)) {
188        OnPropertyChanged("Count");
189        if (addedItems.Count > 0) OnItemsAdded(addedItems);
190        if (removedItems.Count > 0) OnItemsRemoved(removedItems);
191      }
192    }
193
194    public void UnionWith(IEnumerable<T> other) {
195      if (other == null) throw new ArgumentNullException();
196      List<T> items = new List<T>();
197      foreach (T item in other) {
198        if (set.Add(item)) {
199          items.Add(item);
200        }
201      }
202      if (items.Count > 0) {
203        OnPropertyChanged("Count");
204        OnItemsAdded(items);
205      }
206    }
207
208    public void Clear() {
209      if (set.Count > 0) {
210        T[] items = new T[set.Count];
211        set.CopyTo(items);
212        set.Clear();
213        OnPropertyChanged("Count");
214        OnCollectionReset(new T[0], items);
215      }
216    }
217    #endregion
218
219    #region Conversion
220    public ReadOnlyObservableSet<T> AsReadOnly() {
221      return new ReadOnlyObservableSet<T>(this);
222    }
223    public void CopyTo(T[] array) {
224      set.CopyTo(array);
225    }
226    public void CopyTo(T[] array, int arrayIndex) {
227      set.CopyTo(array, arrayIndex);
228    }
229    public void CopyTo(T[] array, int arrayIndex, int count) {
230      set.CopyTo(array, arrayIndex, count);
231    }
232    #endregion
233
234    #region Enumeration
235    public IEnumerator<T> GetEnumerator() {
236      return set.GetEnumerator();
237    }
238    IEnumerator IEnumerable.GetEnumerator() {
239      return set.GetEnumerator();
240    }
241    #endregion
242
243    #region Helpers
244    public void TrimExcess() {
245      set.TrimExcess();
246    }
247    #endregion
248
249    #region Events
250    [field: NonSerialized]
251    public event CollectionItemsChangedEventHandler<T> ItemsAdded;
252    protected virtual void OnItemsAdded(IEnumerable<T> items) {
[3317]253      CollectionItemsChangedEventHandler<T> handler = ItemsAdded;
254      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
[2623]255    }
256
257    [field: NonSerialized]
258    public event CollectionItemsChangedEventHandler<T> ItemsRemoved;
259    protected virtual void OnItemsRemoved(IEnumerable<T> items) {
[3317]260      CollectionItemsChangedEventHandler<T> handler = ItemsRemoved;
261      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
[2623]262    }
263
264    [field: NonSerialized]
265    public event CollectionItemsChangedEventHandler<T> CollectionReset;
266    protected virtual void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
[3317]267      CollectionItemsChangedEventHandler<T> handler = CollectionReset;
268      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
[2623]269    }
270
271    [field: NonSerialized]
272    public event PropertyChangedEventHandler PropertyChanged;
273    protected virtual void OnPropertyChanged(string propertyName) {
[3317]274      PropertyChangedEventHandler handler = PropertyChanged;
275      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
[2623]276    }
277    #endregion
278  }
279}
Note: See TracBrowser for help on using the repository browser.