#if NET20 || NET30 using System.Runtime.Serialization; using System.Security.Permissions; using LinqInternal.Collections; using LinqInternal.Collections.Specialized; namespace System.Collections.Generic { [Serializable] public class HashSet : ISet, ISerializable { private readonly NullAwareDictionary _wrapped; public HashSet() { _wrapped = new NullAwareDictionary(); } public HashSet(IEnumerable collection) { if (collection == null) { throw new ArgumentNullException("collection"); } else { _wrapped = new NullAwareDictionary(); foreach (var item in collection) { _wrapped[item] = null; } } } public HashSet(IEqualityComparer comparer) { _wrapped = new NullAwareDictionary(comparer); } public HashSet(IEnumerable collection, IEqualityComparer comparer) { if (collection == null) { throw new ArgumentNullException("collection"); } else { _wrapped = new NullAwareDictionary(comparer); foreach (var item in collection) { _wrapped[item] = null; } } } [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.SerializationFormatter)] protected HashSet(SerializationInfo info, StreamingContext context) : this() { if (info == null) { throw new ArgumentNullException("info"); } else { _wrapped.GetObjectData(info, context); } } public IEqualityComparer Comparer { get { return _wrapped.Comparer; } } public int Count { get { return _wrapped.Count; } } public bool IsReadOnly { get { return false; } } public static IEqualityComparer> CreateSetComparer() { return HashSetEqualityComparer.Instance; } public bool Add(T item) { if (_wrapped.ContainsKey(item)) { return false; } else { _wrapped[item] = null; return true; } } public void Clear() { _wrapped.Clear(); } public bool Contains(T item) { return _wrapped.ContainsKey(item); } public void CopyTo(T[] array) { if (array == null) { throw new ArgumentNullException("array"); } else if (Count > array.Length) { throw new ArgumentException("the Count property is larger than the size of the destination array."); } else { _wrapped.Keys.CopyTo(array, 0); } } public void CopyTo(T[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0) { throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex < 0"); } if (Count > array.Length - arrayIndex) { throw new ArgumentException("The array can not contain the number of elements.", "array"); } _wrapped.Keys.CopyTo(array, arrayIndex); } public void CopyTo(T[] array, int arrayIndex, int count) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0) { throw new ArgumentOutOfRangeException("arrayIndex", "Non-negative number is required."); } if (count < 0) { throw new ArgumentOutOfRangeException("count", "Non-negative number is required."); } if (count > array.Length - arrayIndex) { throw new ArgumentException("The array can not contain the number of elements.", "array"); } else { var copiedCount = 0; var currentIndex = arrayIndex; foreach (var item in this) { array[currentIndex] = item; currentIndex++; copiedCount++; if (copiedCount >= count) { break; } } } } public void ExceptWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other"); } else { foreach (var item in other) { _wrapped.Remove(item); } } } public IEnumerator GetEnumerator() { return new Enumerator(this); } [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.SerializationFormatter)] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { throw new ArgumentNullException("info"); } else { _wrapped.GetObjectData(info, context); } } void ICollection.Add(T item) { Add(item); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void IntersectWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other"); } else { this.IntersectWith(other, _wrapped.Comparer); } } public bool IsProperSubsetOf(IEnumerable other) { return IsSubsetOf(ToHashSet(other), true); } public bool IsProperSupersetOf(IEnumerable other) { return IsSupersetOf(ToHashSet(other), true); } public bool IsSubsetOf(IEnumerable other) { return IsSubsetOf(ToHashSet(other), false); } public bool IsSupersetOf(IEnumerable other) { return IsSupersetOf(ToHashSet(other), false); } public bool Overlaps(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other"); } foreach (var item in other) { if (_wrapped.ContainsKey(item)) { return true; } } return false; } public bool Remove(T item) { if (_wrapped.ContainsKey(item)) { return _wrapped.Remove(item); } else { return false; } } public int RemoveWhere(Predicate match) { return Extensions.RemoveWhere(this, match); } public bool SetEquals(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other"); } var containsCount = 0; foreach (var item in ToHashSet(other)) { if (!_wrapped.ContainsKey(item)) { return false; } else { containsCount++; } } return containsCount == _wrapped.Count; } public void SymmetricExceptWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other"); } var tmpSet = new HashSet(other); foreach (var item in tmpSet) { if (_wrapped.ContainsKey(item)) { _wrapped.Remove(item); } else { _wrapped[item] = null; } } } public void TrimExcess() { //Empty } public void UnionWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other"); } foreach (var item in other) { if (!_wrapped.ContainsKey(item)) { _wrapped[item] = null; } } } private bool IsSubsetOf(IEnumerable other, bool proper) { if (other == null) { throw new ArgumentNullException("other"); } else { var elementCount = 0; var matchCount = 0; foreach (var item in other) { elementCount++; if (_wrapped.ContainsKey(item)) { matchCount++; } } if (proper) { return matchCount == _wrapped.Count && elementCount > _wrapped.Count; } else { return matchCount == _wrapped.Count; } } } private bool IsSupersetOf(IEnumerable other, bool proper) { if (other == null) { throw new ArgumentNullException("other"); } else { var elementCount = 0; foreach (var item in other) { elementCount++; if (!_wrapped.ContainsKey(item)) { return false; } } if (proper) { return elementCount < _wrapped.Count; } else { return true; } } } private IEnumerable ToHashSet(IEnumerable other) { var test = other as HashSet; var comparer = Comparer; if (test != null && comparer.Equals(test.Comparer)) { return test; } else { return new HashSet(other, comparer); } } public struct Enumerator : IEnumerator { private readonly IEnumerator> _enumerator; private bool _valid; private T _current; public Enumerator(HashSet hashSet) { _enumerator = hashSet._wrapped.GetEnumerator(); _valid = false; _current = default(T); } public T Current { get { return _current; } } object IEnumerator.Current { get { if (_valid) { return _current; } else { throw new InvalidOperationException("Call MoveNext first or use IEnumerator"); } } } public void Dispose() { var enumerator = _enumerator; if (enumerator != null) { enumerator.Dispose(); } } void IEnumerator.Reset() { _valid = false; var enumerator = _enumerator; if (enumerator != null) { _current = _enumerator.Current.Key; _enumerator.Reset(); } } public bool MoveNext() { var enumerator = _enumerator; if (enumerator != null) { _valid = _enumerator.MoveNext(); _current = _enumerator.Current.Key; return _valid; } return false; } } private sealed class HashSetEqualityComparer : IEqualityComparer> { public static readonly HashSetEqualityComparer Instance = new HashSetEqualityComparer(); public bool Equals(HashSet left, HashSet right) { if (left == right) { return true; } else { if (left == null || right == null || left.Count != right.Count) { return false; } else { foreach (var item in left) { if (!right.Contains(item)) { return false; } } return true; } } } public int GetHashCode(HashSet hashset) { try { IEqualityComparer comparer = EqualityComparer.Default; var hash = 0; foreach (var item in hashset) { hash ^= comparer.GetHashCode(item); } return hash; } catch (NullReferenceException) { return 0; } } } } } #endif