context: 
  /*
   *  MetaphysicsIndustries.Collections
   *  Copyright (C) 2014 Metaphysics Industries, Inc., Richard Sartor
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   * 
   */
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Diagnostics;
  using System.Runtime.Serialization;
  
  namespace MetaphysicsIndustries.Collections
  {
      [Serializable]
      [DebuggerDisplay("Count = {Count}")]
      [DebuggerTypeProxy(typeof(CollectionDebuggerTypeProxy<>))]
      public class Set<T> : ICollection<T>, ISerializable
      {
          private IDictionary<T, bool> _dictionary = new Dictionary<T, bool>();
  
          public Set()
              : this(new T[0])
          {
          }
  
          public Set(IEnumerable<T> initialContents)
          {
              if (initialContents != null)
              {
                  AddRange(initialContents);
              }
          }
  
          public Set(params T[] initialContents)
              : this((IEnumerable<T>)initialContents)
          {
          }
  
          public static Set<T> FromArray<U>(params U[] items)
              where U : T
          {
              return FromCollection(items);
          }
  
          public static Set<T> FromCollection<U>(IEnumerable<U> items)
              where U : T
          {
              Set<T> set = new Set<T>();
              set.AddRange(items);
              return set;
          }
  
          protected Set(SerializationInfo info, StreamingContext context)
          {
              List<T> list = new List<T>();
              int i;
              for (i = 0; i < info.MemberCount; i++)
              {
                  list.Add((T)info.GetValue(i.ToString(), typeof(T)));
              }
  
              AddRange(list);
          }
  
          public void GetObjectData(SerializationInfo info, StreamingContext context)
          {
              T[] array = this.ToArray();
              int i;
              for (i = 0; i < array.Length; i++)
              {
                  info.AddValue(i.ToString(), array[i]);
              }
          }
  
          //public static implicit operator T[](Set<T> s)
          //{
          //    return s.ToArray();
          //}
  
          //public void Dispose()
          //{
          //    //T[] r = new T[Count];
          //    //CopyTo(r, 0);
          //    //foreach (T t in r)
          //    //{
          //    //    Remove(t);
          //    //}
          //    //_dictionary.Clear();
  
          //    //if (_dictionary != null)
          //    //{
          //    //    Clear();
          //    //    _dictionary = null;
          //    //}
          //}
  
          public static Set<T> Union(params T[] items)
          {
              return Union((IEnumerable<T>)items);
          }
          public static Set<T> Union(IEnumerable<T> items)
          {
              return new Set<T>(items);
          }
          public static Set<T> Union(IEnumerable<T> a, params T[] b)
          {
              return Union(a, (IEnumerable<T>)b);
          }
          public static Set<T> Union(IEnumerable<T> a, IEnumerable<T> b)
          {
              Set<T> s = new Set<T>(a);
  
              s.AddRange(b);
  
              return s;
          }
          public static Set<T> Union(params IEnumerable<T>[] sets)
          {
              Set<T> s = new Set<T>();
  
              foreach (IEnumerable<T> set in sets)
              {
                  s.AddRange(set);
              }
  
              return s;
          }
  
          //lots of potential performance problems here.
          //public static T[] Intersection(params T[][] sets)
          //{
          //    if (sets == null) { throw new ArgumentNullException("sets"); }
          //    if (sets.Length < 1)
          //    {
          //        return new T();
          //    }
          //    Set<T> set = new Set<T>(set[0]);
          //    int i;
          //    for (i = 1; i < sets.Length; i++)
          //    {
          //        set 
          //    }
          //}
          public static T[] Intersection(T[] a, T[] b)
          {
              return Intersection(new Set<T>(a), b).ToArray();
          }
          //public static Set<T> Intersection(Set<T> a, params T[] b)
          //{
          //    return Intersection(a, (IEnumerable<T>)b);
          //}
          public static Set<T> Intersection(Set<T> a, IEnumerable<T> b)
          {
              Set<T> s = new Set<T>();
  
              foreach (T t in b)
              {
                  if (a.Contains(t))
                  {
                      s.Add(t);
                  }
              }
  
              return s;
          }
  
          //public static Set<T> Difference(Set<T> a, params T[] b)
          //{
          //    return Difference(a, (IEnumerable<T>)b);
          //}
          //public static Set<T> Difference(Set<T> a, IEnumerable<T> b)
          //{
          //    Set<T> s = new Set<T>(a);
  
          //    s.RemoveRange(b);
  
          //    return s;
          //}
          public static T[] Difference(T[] a, T[] b)
          {
              Set<T> set = new Set<T>(a);
              set.RemoveRange(b);
              return set.ToArray();
          }
  
          public U[] Extract<U>()
              where U : T
          {
              return Collection.Extract<T, U>(this);
          }
  
          public bool IsEmpty
          {
              get
              {
  
gt:                 return Count <= 0;