using System; using System.Collections; using System.Collections.Generic; using System.Linq; using ICD.Common.Properties; namespace ICD.Common.Utils.Collections { /// /// A collection containing only unique items. /// /// public sealed class IcdHashSet : ICollection { private readonly Dictionary m_Dict; #region Properties /// /// Returns a new, empty hashset. /// [PublicAPI] public static IcdHashSet NullSet { get { return new IcdHashSet(); } } /// /// Gets the number of items contained in the . /// /// /// The number of items contained in the . /// public int Count { get { return m_Dict.Count; } } /// /// Gets a value indicating whether the is read-only. /// /// /// true if the is read-only; otherwise, false. /// public bool IsReadOnly { get { return false; } } #endregion #region Constructors /// /// Constructor. /// public IcdHashSet() { m_Dict = new Dictionary(); } /// /// Constructor. /// /// public IcdHashSet(IEnumerable items) : this() { if (items == null) return; AddRange(items); } #endregion #region Methods [PublicAPI] public IcdHashSet Union(IEnumerable set) { IcdHashSet unionSet = new IcdHashSet(this); if (set == null) return unionSet; unionSet.AddRange(set); return unionSet; } [PublicAPI] public IcdHashSet Subtract(IEnumerable set) { IcdHashSet subtractSet = new IcdHashSet(this); if (set == null) return subtractSet; foreach (T item in set) subtractSet.Remove(item); return subtractSet; } [PublicAPI] public bool IsSubsetOf(IcdHashSet set) { IcdHashSet setToCompare = set ?? NullSet; return this.All(setToCompare.Contains); } [PublicAPI] public IcdHashSet Intersection(IcdHashSet set) { IcdHashSet intersectionSet = NullSet; if (set == null) return intersectionSet; foreach (T item in this.Where(set.Contains)) intersectionSet.Add(item); foreach (T item in set.Where(Contains)) intersectionSet.Add(item); return intersectionSet; } /// /// Returns items that are not common between both sets. /// /// /// [PublicAPI] public IcdHashSet NonIntersection(IcdHashSet set) { return Subtract(set).Union(set.Subtract(this)); } [PublicAPI] public bool IsProperSubsetOf(IcdHashSet set) { IcdHashSet setToCompare = set ?? NullSet; // Is a proper subset if A is a subset of B and A != B return (IsSubsetOf(setToCompare) && !setToCompare.IsSubsetOf(this)); } [PublicAPI] public bool IsSupersetOf(IcdHashSet set) { IcdHashSet setToCompare = set ?? NullSet; return setToCompare.IsSubsetOf(this); } [PublicAPI] public bool IsProperSupersetOf(IcdHashSet set) { IcdHashSet setToCompare = set ?? NullSet; // B is a proper superset of A if B is a superset of A and A != B return (IsSupersetOf(setToCompare) && !setToCompare.IsSupersetOf(this)); } #endregion #region ICollection Members /// /// Adds the item to the collection. Returns false if the item already exists. /// /// /// public bool Add(T item) { // ReSharper disable CompareNonConstrainedGenericWithNull if (item == null) // ReSharper restore CompareNonConstrainedGenericWithNull throw new ArgumentNullException("item"); if (m_Dict.ContainsKey(item)) return false; m_Dict[item] = null; return true; } /// /// Adds the item to the collection. /// /// void ICollection.Add(T item) { Add(item); } /// /// Adds each of the items in the sequence to the collection. /// /// public void AddRange(IEnumerable items) { foreach (T item in items) Add(item); } /// /// Removes all items from the . /// /// The is read-only. public void Clear() { m_Dict.Clear(); } /// /// Returns true if the IcdHashSet contains the given item. /// /// /// public bool Contains(T item) { return m_Dict.ContainsKey(item); } /// /// Copies the items of the to an , starting at a particular index. /// /// The one-dimensional that is the destination of the items copied from . The must have zero-based indexing.The zero-based index in at which copying begins. is null. is less than 0. is multidimensional.-or- is equal to or greater than the length of .-or-The number of items in the source is greater than the available space from to the end of the destination .-or-Type T cannot be cast automatically to the type of the destination . public void CopyTo(T[] array, int arrayIndex) { m_Dict.Keys.CopyTo(array, arrayIndex); } /// /// Removes the first occurrence of a specific object from the . /// /// /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . /// /// The object to remove from the .The is read-only. public bool Remove(T item) { return m_Dict.Remove(item); } #endregion #region Implementation of IEnumerable /// /// Returns an enumerator that iterates through the collection. /// /// /// A that can be used to iterate through the collection. /// /// 1 public IEnumerator GetEnumerator() { return m_Dict.Keys.GetEnumerator(); } /// /// Returns an enumerator that iterates through a collection. /// /// /// An object that can be used to iterate through the collection. /// /// 2 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion } }