Hash Set 2 : Set « Collections Data Structure « C# / C Sharp






Hash Set 2

 
//GNU Library General Public License (LGPL)
//http://dac.codeplex.com/license
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;

namespace RaisingStudio.Collections.Generic
{
    [Serializable]
    public class HashSet<T> : ICollection<T>, IEnumerable<T>, IEnumerable, ISerializable, IDeserializationCallback
    {
        private const string CapacityName = "Capacity";
        private const string ComparerName = "Comparer";
        private const string ElementsName = "Elements";
        private const int GrowthFactor = 2;
        private const int Lower31BitMask = 0x7fffffff;
        private int[] m_buckets;
        private IEqualityComparer<T> m_comparer;
        private int m_count;
        private int m_freeList;
        private int m_lastIndex;
        private Slot<T>[] m_slots;
        private int m_version;
        private const int ShrinkThreshold = 3;
        private const int StackAllocThreshold = 100;
        private const string VersionName = "Version";

        public HashSet()
            : this(EqualityComparer<T>.Default)
        {
        }

        public HashSet(IEnumerable<T> collection)
            : this(collection, EqualityComparer<T>.Default)
        {
        }

        public HashSet(IEqualityComparer<T> comparer)
        {
            if (comparer == null)
            {
                comparer = EqualityComparer<T>.Default;
            }
            this.m_comparer = comparer;
            this.m_lastIndex = 0;
            this.m_count = 0;
            this.m_freeList = -1;
            this.m_version = 0;
        }

        public HashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer)
            : this(comparer)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }
            int capacity = 0;
            ICollection<T> is2 = collection as ICollection<T>;
            if (is2 != null)
            {
                capacity = is2.Count;
            }
            this.Initialize(capacity);
            this.UnionWith(collection);
            if (((this.m_count == 0) && (this.m_slots.Length > HashHelpers.GetMinPrime())) || ((this.m_count > 0) && ((this.m_slots.Length / this.m_count) > 3)))
            {
                this.TrimExcess();
            }
        }

        private SerializationInfo m_siInfo;
        protected HashSet(SerializationInfo info, StreamingContext context)
        {
            this.m_siInfo = info;
        }

        public bool Add(T item)
        {
            return this.AddIfNotPresent(item);
        }

        private bool AddIfNotPresent(T value)
        {
            int freeList;
            if (this.m_buckets == null)
            {
                this.Initialize(0);
            }
            int hashCode = this.InternalGetHashCode(value);
            int index = hashCode % this.m_buckets.Length;
            for (int i = this.m_buckets[hashCode % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
            {
                if ((this.m_slots[i].hashCode == hashCode) && this.m_comparer.Equals(this.m_slots[i].value, value))
                {
                    return false;
                }
            }
            if (this.m_freeList >= 0)
            {
                freeList = this.m_freeList;
                this.m_freeList = this.m_slots[freeList].next;
            }
            else
            {
                if (this.m_lastIndex == this.m_slots.Length)
                {
                    this.IncreaseCapacity();
                    index = hashCode % this.m_buckets.Length;
                }
                freeList = this.m_lastIndex;
                this.m_lastIndex++;
            }
            this.m_slots[freeList].hashCode = hashCode;
            this.m_slots[freeList].value = value;
            this.m_slots[freeList].next = this.m_buckets[index] - 1;
            this.m_buckets[index] = freeList + 1;
            this.m_count++;
            this.m_version++;
            return true;
        }

        private bool AddOrGetLocation(T value, out int location)
        {
            int freeList;
            int hashCode = this.InternalGetHashCode(value);
            int index = hashCode % this.m_buckets.Length;
            for (int i = this.m_buckets[hashCode % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
            {
                if ((this.m_slots[i].hashCode == hashCode) && this.m_comparer.Equals(this.m_slots[i].value, value))
                {
                    location = i;
                    return false;
                }
            }
            if (this.m_freeList >= 0)
            {
                freeList = this.m_freeList;
                this.m_freeList = this.m_slots[freeList].next;
            }
            else
            {
                if (this.m_lastIndex == this.m_slots.Length)
                {
                    this.IncreaseCapacity();
                    index = hashCode % this.m_buckets.Length;
                }
                freeList = this.m_lastIndex;
                this.m_lastIndex++;
            }
            this.m_slots[freeList].hashCode = hashCode;
            this.m_slots[freeList].value = value;
            this.m_slots[freeList].next = this.m_buckets[index] - 1;
            this.m_buckets[index] = freeList + 1;
            this.m_count++;
            this.m_version++;
            location = freeList;
            return true;
        }

        private static bool AreEqualityComparersEqual(HashSet<T> set1, HashSet<T> set2)
        {
            return set1.Comparer.Equals(set2.Comparer);
        }

        [SecurityCritical]
        private unsafe ElementCount<T> CheckUniqueAndUnfoundElements(IEnumerable<T> other, bool returnIfUnfound)
        {
            ElementCount<T> count;
            if (this.m_count != 0)
            {
                BitHelper helper;
                int length = BitHelper.ToIntArrayLength(this.m_lastIndex);
                if (length <= 100)
                {
                    int* bitArrayPtr = stackalloc int[length];
                    helper = new BitHelper(bitArrayPtr, length);
                }
                else
                {
                    int[] bitArray = new int[length];
                    helper = new BitHelper(bitArray, length);
                }
                int num4 = 0;
                int num5 = 0;
                foreach (T local in other)
                {
                    int bitPosition = this.InternalIndexOf(local);
                    if (bitPosition >= 0)
                    {
                        if (!helper.IsMarked(bitPosition))
                        {
                            helper.MarkBit(bitPosition);
                            num5++;
                        }
                    }
                    else
                    {
                        num4++;
                        if (returnIfUnfound)
                        {
                            break;
                        }
                    }
                }
                count.uniqueCount = num5;
                count.unfoundCount = num4;
                return count;
            }
            int num = 0;
            using (IEnumerator<T> enumerator = other.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    T current = enumerator.Current;
                    num++;
                    goto Label_0039;
                }
            }
        Label_0039:
            count.uniqueCount = 0;
            count.unfoundCount = num;
            return count;
        }

        public void Clear()
        {
            if (this.m_lastIndex > 0)
            {
                Array.Clear(this.m_slots, 0, this.m_lastIndex);
                Array.Clear(this.m_buckets, 0, this.m_buckets.Length);
                this.m_lastIndex = 0;
                this.m_count = 0;
                this.m_freeList = -1;
            }
            this.m_version++;
        }

        public bool Contains(T item)
        {
            if (this.m_buckets != null)
            {
                int hashCode = this.InternalGetHashCode(item);
                for (int i = this.m_buckets[hashCode % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
                {
                    if ((this.m_slots[i].hashCode == hashCode) && this.m_comparer.Equals(this.m_slots[i].value, item))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private bool ContainsAllElements(IEnumerable<T> other)
        {
            foreach (T local in other)
            {
                if (!this.Contains(local))
                {
                    return false;
                }
            }
            return true;
        }

        public void CopyTo(T[] array)
        {
            this.CopyTo(array, 0, this.m_count);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            this.CopyTo(array, arrayIndex, this.m_count);
        }

        public void CopyTo(T[] array, int arrayIndex, int count)
        {
            if (array == null)
            {
                throw new ArgumentNullException("array");
            }
            if (arrayIndex < 0)
            {
                throw new ArgumentOutOfRangeException("arrayIndex", "ArgumentOutOfRange_NeedNonNegNum");
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_NeedNonNegNum");
            }
            if ((arrayIndex > array.Length) || (count > (array.Length - arrayIndex)))
            {
                throw new ArgumentException("Arg_ArrayPlusOffTooSmall");
            }
            int num = 0;
            for (int i = 0; (i < this.m_lastIndex) && (num < count); i++)
            {
                if (this.m_slots[i].hashCode >= 0)
                {
                    array[arrayIndex + num] = this.m_slots[i].value;
                    num++;
                }
            }
        }

        public static IEqualityComparer<HashSet<T>> CreateSetComparer()
        {
            return new HashSetEqualityComparer<T>();
        }

        public void ExceptWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count != 0)
            {
                if (other == this)
                {
                    this.Clear();
                }
                else
                {
                    foreach (T local in other)
                    {
                        this.Remove(local);
                    }
                }
            }
        }

        public Enumerator<T> GetEnumerator()
        {
            return new Enumerator<T>((HashSet<T>)this);
        }

#if (PocketPC || Smartphone)
#else
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
#endif
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
            info.AddValue("Version", this.m_version);
            info.AddValue("Comparer", this.m_comparer, typeof(IEqualityComparer<T>));
            info.AddValue("Capacity", (this.m_buckets == null) ? 0 : this.m_buckets.Length);
            if (this.m_buckets != null)
            {
                T[] array = new T[this.m_count];
                this.CopyTo(array);
                info.AddValue("Elements", array, typeof(T[]));
            }
        }

        internal static bool HashSetEquals(HashSet<T> set1, HashSet<T> set2, IEqualityComparer<T> comparer)
        {
            if (set1 == null)
            {
                return (set2 == null);
            }
            if (set2 == null)
            {
                return false;
            }
            if (HashSet<T>.AreEqualityComparersEqual(set1, set2))
            {
                if (set1.Count != set2.Count)
                {
                    return false;
                }
                foreach (T local in set2)
                {
                    if (!set1.Contains(local))
                    {
                        return false;
                    }
                }
                return true;
            }
            foreach (T local2 in set2)
            {
                bool flag = false;
                foreach (T local3 in set1)
                {
                    if (comparer.Equals(local2, local3))
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    return false;
                }
            }
            return true;
        }

        private void IncreaseCapacity()
        {
            int min = this.m_count * 2;
            if (min < 0)
            {
                min = this.m_count;
            }
            int prime = HashHelpers.GetPrime(min);
            if (prime <= this.m_count)
            {
                throw new ArgumentException("Arg_HSCapacityOverflow");
            }
            Slot<T>[] destinationArray = new Slot<T>[prime];
            if (this.m_slots != null)
            {
                Array.Copy(this.m_slots, 0, destinationArray, 0, this.m_lastIndex);
            }
            int[] numArray = new int[prime];
            for (int i = 0; i < this.m_lastIndex; i++)
            {
                int index = destinationArray[i].hashCode % prime;
                destinationArray[i].next = numArray[index] - 1;
                numArray[index] = i + 1;
            }
            this.m_slots = destinationArray;
            this.m_buckets = numArray;
        }

        private void Initialize(int capacity)
        {
            int prime = HashHelpers.GetPrime(capacity);
            this.m_buckets = new int[prime];
            this.m_slots = new Slot<T>[prime];
        }

        private int InternalGetHashCode(T item)
        {
            if (item == null)
            {
                return 0;
            }
            return (this.m_comparer.GetHashCode(item) & 0x7fffffff);
        }

        private int InternalIndexOf(T item)
        {
            int hashCode = this.InternalGetHashCode(item);
            for (int i = this.m_buckets[hashCode % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
            {
                if ((this.m_slots[i].hashCode == hashCode) && this.m_comparer.Equals(this.m_slots[i].value, item))
                {
                    return i;
                }
            }
            return -1;
        }

        [SecurityCritical]
        public void IntersectWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count != 0)
            {
                ICollection<T> is2 = other as ICollection<T>;
                if (is2 != null)
                {
                    if (is2.Count == 0)
                    {
                        this.Clear();
                        return;
                    }
                    HashSet<T> set = other as HashSet<T>;
                    if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                    {
                        this.IntersectWithHashSetWithSameEC(set);
                        return;
                    }
                }
                this.IntersectWithEnumerable(other);
            }
        }

        [SecurityCritical]
        private unsafe void IntersectWithEnumerable(IEnumerable<T> other)
        {
            BitHelper helper;
            int lastIndex = this.m_lastIndex;
            int length = BitHelper.ToIntArrayLength(lastIndex);
            if (length <= 100)
            {
                int* bitArrayPtr = stackalloc int[length];
                helper = new BitHelper(bitArrayPtr, length);
            }
            else
            {
                int[] bitArray = new int[length];
                helper = new BitHelper(bitArray, length);
            }
            foreach (T local in other)
            {
                int bitPosition = this.InternalIndexOf(local);
                if (bitPosition >= 0)
                {
                    helper.MarkBit(bitPosition);
                }
            }
            for (int i = 0; i < lastIndex; i++)
            {
                if ((this.m_slots[i].hashCode >= 0) && !helper.IsMarked(i))
                {
                    this.Remove(this.m_slots[i].value);
                }
            }
        }

        private void IntersectWithHashSetWithSameEC(HashSet<T> other)
        {
            for (int i = 0; i < this.m_lastIndex; i++)
            {
                if (this.m_slots[i].hashCode >= 0)
                {
                    T item = this.m_slots[i].value;
                    if (!other.Contains(item))
                    {
                        this.Remove(item);
                    }
                }
            }
        }

        [SecurityCritical]
        public bool IsProperSubsetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (is2 != null)
            {
                if (this.m_count == 0)
                {
                    return (is2.Count > 0);
                }
                HashSet<T> set = other as HashSet<T>;
                if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                {
                    if (this.m_count >= set.Count)
                    {
                        return false;
                    }
                    return this.IsSubsetOfHashSetWithSameEC(set);
                }
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, false);
            return ((count.uniqueCount == this.m_count) && (count.unfoundCount > 0));
        }

        [SecurityCritical]
        public bool IsProperSupersetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count == 0)
            {
                return false;
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (is2 != null)
            {
                if (is2.Count == 0)
                {
                    return true;
                }
                HashSet<T> set = other as HashSet<T>;
                if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                {
                    if (set.Count >= this.m_count)
                    {
                        return false;
                    }
                    return this.ContainsAllElements(set);
                }
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, true);
            return ((count.uniqueCount < this.m_count) && (count.unfoundCount == 0));
        }

        [SecurityCritical]
        public bool IsSubsetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count == 0)
            {
                return true;
            }
            HashSet<T> set = other as HashSet<T>;
            if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
            {
                if (this.m_count > set.Count)
                {
                    return false;
                }
                return this.IsSubsetOfHashSetWithSameEC(set);
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, false);
            return ((count.uniqueCount == this.m_count) && (count.unfoundCount >= 0));
        }

        private bool IsSubsetOfHashSetWithSameEC(HashSet<T> other)
        {
            foreach (T local in this)
            {
                if (!other.Contains(local))
                {
                    return false;
                }
            }
            return true;
        }

        public bool IsSupersetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (is2 != null)
            {
                if (is2.Count == 0)
                {
                    return true;
                }
                HashSet<T> set = other as HashSet<T>;
                if (((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set)) && (set.Count > this.m_count))
                {
                    return false;
                }
            }
            return this.ContainsAllElements(other);
        }

        public virtual void OnDeserialization(object sender)
        {
            if (this.m_siInfo != null)
            {
                int num = this.m_siInfo.GetInt32("Capacity");
                this.m_comparer = (IEqualityComparer<T>)this.m_siInfo.GetValue("Comparer", typeof(IEqualityComparer<T>));
                this.m_freeList = -1;
                if (num != 0)
                {
                    this.m_buckets = new int[num];
                    this.m_slots = new Slot<T>[num];
                    T[] localArray = (T[])this.m_siInfo.GetValue("Elements", typeof(T[]));
                    if (localArray == null)
                    {
                        throw new SerializationException("Serialization_MissingKeys");
                    }
                    for (int i = 0; i < localArray.Length; i++)
                    {
                        this.AddIfNotPresent(localArray[i]);
                    }
                }
                else
                {
                    this.m_buckets = null;
                }
                this.m_version = this.m_siInfo.GetInt32("Version");
                this.m_siInfo = null;
            }
        }

        public bool Overlaps(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count != 0)
            {
                foreach (T local in other)
                {
                    if (this.Contains(local))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public bool Remove(T item)
        {
            if (this.m_buckets != null)
            {
                int hashCode = this.InternalGetHashCode(item);
                int index = hashCode % this.m_buckets.Length;
                int num3 = -1;
                for (int i = this.m_buckets[index] - 1; i >= 0; i = this.m_slots[i].next)
                {
                    if ((this.m_slots[i].hashCode == hashCode) && this.m_comparer.Equals(this.m_slots[i].value, item))
                    {
                        if (num3 < 0)
                        {
                            this.m_buckets[index] = this.m_slots[i].next + 1;
                        }
                        else
                        {
                            this.m_slots[num3].next = this.m_slots[i].next;
                        }
                        this.m_slots[i].hashCode = -1;
                        this.m_slots[i].value = default(T);
                        this.m_slots[i].next = this.m_freeList;
                        this.m_freeList = i;
                        this.m_count--;
                        this.m_version++;
                        return true;
                    }
                    num3 = i;
                }
            }
            return false;
        }

        public int RemoveWhere(Predicate<T> match)
        {
            if (match == null)
            {
                throw new ArgumentNullException("match");
            }
            int num = 0;
            for (int i = 0; i < this.m_lastIndex; i++)
            {
                if (this.m_slots[i].hashCode >= 0)
                {
                    T local = this.m_slots[i].value;
                    if (match(local) && this.Remove(local))
                    {
                        num++;
                    }
                }
            }
            return num;
        }

        [SecurityCritical]
        public bool SetEquals(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            HashSet<T> set = other as HashSet<T>;
            if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
            {
                if (this.m_count != set.Count)
                {
                    return false;
                }
                return this.ContainsAllElements(set);
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (((is2 != null) && (this.m_count == 0)) && (is2.Count > 0))
            {
                return false;
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, true);
            return ((count.uniqueCount == this.m_count) && (count.unfoundCount == 0));
        }

        [SecurityCritical]
        public void SymmetricExceptWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count == 0)
            {
                this.UnionWith(other);
            }
            else if (other == this)
            {
                this.Clear();
            }
            else
            {
                HashSet<T> set = other as HashSet<T>;
                if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                {
                    this.SymmetricExceptWithUniqueHashSet(set);
                }
                else
                {
                    this.SymmetricExceptWithEnumerable(other);
                }
            }
        }

        [SecurityCritical]
        private unsafe void SymmetricExceptWithEnumerable(IEnumerable<T> other)
        {
            BitHelper helper;
            BitHelper helper2;
            int lastIndex = this.m_lastIndex;
            int length = BitHelper.ToIntArrayLength(lastIndex);
            if (length <= 50)
            {
                int* bitArrayPtr = stackalloc int[length];
                helper = new BitHelper(bitArrayPtr, length);
                int* numPtr2 = stackalloc int[length];
                helper2 = new BitHelper(numPtr2, length);
            }
            else
            {
                int[] bitArray = new int[length];
                helper = new BitHelper(bitArray, length);
                int[] numArray2 = new int[length];
                helper2 = new BitHelper(numArray2, length);
            }
            foreach (T local in other)
            {
                int location = 0;
                if (this.AddOrGetLocation(local, out location))
                {
                    helper2.MarkBit(location);
                }
                else if ((location < lastIndex) && !helper2.IsMarked(location))
                {
                    helper.MarkBit(location);
                }
            }
            for (int i = 0; i < lastIndex; i++)
            {
                if (helper.IsMarked(i))
                {
                    this.Remove(this.m_slots[i].value);
                }
            }
        }

        private void SymmetricExceptWithUniqueHashSet(HashSet<T> other)
        {
            foreach (T local in other)
            {
                if (!this.Remove(local))
                {
                    this.AddIfNotPresent(local);
                }
            }
        }

        void ICollection<T>.Add(T item)
        {
            this.AddIfNotPresent(item);
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            return new Enumerator<T>((HashSet<T>)this);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator<T>((HashSet<T>)this);
        }

        internal T[] ToArray()
        {
            T[] array = new T[this.Count];
            this.CopyTo(array);
            return array;
        }

        public void TrimExcess()
        {
            if (this.m_count == 0)
            {
                this.m_buckets = null;
                this.m_slots = null;
                this.m_version++;
            }
            else
            {
                int prime = HashHelpers.GetPrime(this.m_count);
                Slot<T>[] slotArray = new Slot<T>[prime];
                int[] numArray = new int[prime];
                int index = 0;
                for (int i = 0; i < this.m_lastIndex; i++)
                {
                    if (this.m_slots[i].hashCode >= 0)
                    {
                        slotArray[index] = this.m_slots[i];
                        int num4 = slotArray[index].hashCode % prime;
                        slotArray[index].next = numArray[num4] - 1;
                        numArray[num4] = index + 1;
                        index++;
                    }
                }
                this.m_lastIndex = index;
                this.m_slots = slotArray;
                this.m_buckets = numArray;
                this.m_freeList = -1;
            }
        }

        public void UnionWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            foreach (T local in other)
            {
                this.AddIfNotPresent(local);
            }
        }

        public IEqualityComparer<T> Comparer
        {
            get
            {
                return this.m_comparer;
            }
        }

        public int Count
        {
            get
            {
                return this.m_count;
            }
        }

        bool ICollection<T>.IsReadOnly
        {
            get
            {
                return false;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct ElementCount<T>
        {
            internal int uniqueCount;
            internal int unfoundCount;
        }

        [Serializable, StructLayout(LayoutKind.Sequential)]
#if (PocketPC || Smartphone)
#else
        [HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
#endif
        public struct Enumerator<T> : IEnumerator<T>, IDisposable, IEnumerator
        {
            private HashSet<T> set;
            private int index;
            private int version;
            private T current;
            internal Enumerator(HashSet<T> set)
            {
                this.set = set;
                this.index = 0;
                this.version = set.m_version;
                this.current = default(T);
            }

            public void Dispose()
            {
            }

            public bool MoveNext()
            {
                if (this.version != this.set.m_version)
                {
                    throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
                }
                while (this.index < this.set.m_lastIndex)
                {
                    if (this.set.m_slots[this.index].hashCode >= 0)
                    {
                        this.current = this.set.m_slots[this.index].value;
                        this.index++;
                        return true;
                    }
                    this.index++;
                }
                this.index = this.set.m_lastIndex + 1;
                this.current = default(T);
                return false;
            }

            public T Current
            {
                get
                {
                    return this.current;
                }
            }
            object IEnumerator.Current
            {
                get
                {
                    if ((this.index == 0) || (this.index == (this.set.m_lastIndex + 1)))
                    {
                        throw new InvalidOperationException("InvalidOperation_EnumOpCantHappen");
                    }
                    return this.Current;
                }
            }
            void IEnumerator.Reset()
            {
                if (this.version != this.set.m_version)
                {
                    throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
                }
                this.index = 0;
                this.current = default(T);
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct Slot<T>
        {
            internal int hashCode;
            internal T value;
            internal int next;
        }
    }
    [Serializable]
    internal class HashSetEqualityComparer<T> : IEqualityComparer<HashSet<T>>
    {
        private IEqualityComparer<T> m_comparer;

        public HashSetEqualityComparer()
        {
            this.m_comparer = EqualityComparer<T>.Default;
        }

        public HashSetEqualityComparer(IEqualityComparer<T> comparer)
        {
            if (this.m_comparer == null)
            {
                this.m_comparer = EqualityComparer<T>.Default;
            }
            else
            {
                this.m_comparer = comparer;
            }
        }

        public override bool Equals(object obj)
        {
            HashSetEqualityComparer<T> comparer = obj as HashSetEqualityComparer<T>;
            if (comparer == null)
            {
                return false;
            }
            return (this.m_comparer == comparer.m_comparer);
        }

        public bool Equals(HashSet<T> x, HashSet<T> y)
        {
            return HashSet<T>.HashSetEquals(x, y, this.m_comparer);
        }

        public override int GetHashCode()
        {
            return this.m_comparer.GetHashCode();
        }

        public int GetHashCode(HashSet<T> obj)
        {
            int num = 0;
            if (obj != null)
            {
                foreach (T local in obj)
                {
                    num ^= this.m_comparer.GetHashCode(local) & 0x7fffffff;
                }
            }
            return num;
        }
    }
}

   
  








Related examples in the same category

1.Put the Set class into its own namespacePut the Set class into its own namespace
2.Generic Set
3.Hash Set