Usando HashSet en C # 2.0, compatible con 3.5

Realmente quiero usar hashsets en mi progtwig. Usar un diccionario se siente feo. Probablemente empezaré a usar VS2008 con .Net 3.5 algún día, entonces mi ideal sería que aunque no puedo (¿o puedo?) Usar hashsets en VS2005, cuando empiece a usar .NET 3.5, no quiero tener que cambiar mucho, en todo caso, para cambiar al uso de estos hashsets.

Me pregunto si alguien conoce una implementación de hashset existente diseñada con esto en mente, o una forma de usar el 3.5 hashset en VS2005.

HashSet puede usar HashSet en una aplicación 2.0, simplemente haga referencia a System.Core.dll y debería estar listo para comenzar.

Nota: Esto requeriría que instale el framework .NET 3.5, que es gratuito y está separado de Visual Studio. Una vez que tenga instalado, tendrá el nuevo ensamblado System.Core que contiene el tipo HashSet . Como todas las versiones de .NET Framework 2.0 – 3.5 comparten el mismo CLR, puede usar este ensamblado en su aplicación 2.0 sin problemas.

Aquí hay uno que escribí para 2.0 que usa un Diccionario internamente. No es una coincidencia exacta del 3.5 HashSet , pero hace el trabajo por mí.

 using System; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; public class HashSet : ICollection, ISerializable, IDeserializationCallback { private readonly Dictionary dict; public HashSet() { dict = new Dictionary(); } public HashSet(IEnumerable items) : this() { if (items == null) { return; } foreach (T item in items) { Add(item); } } public HashSet NullSet { get { return new HashSet(); } } #region ICollection Members public void Add(T item) { if (null == item) { throw new ArgumentNullException("item"); } dict[item] = null; } ///  /// Removes all items from the . ///  /// The  is read-only.  public void Clear() { dict.Clear(); } public bool Contains(T item) { return 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) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0 || arrayIndex >= array.Length || arrayIndex >= Count) { throw new ArgumentOutOfRangeException("arrayIndex"); } 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 dict.Remove(item); } ///  /// Gets the number of items contained in the . ///  ///  /// The number of items contained in the . ///  public int Count { get { return 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 public HashSet Union(HashSet set) { HashSet unionSet = new HashSet(this); if (null == set) { return unionSet; } foreach (T item in set) { if (unionSet.Contains(item)) { continue; } unionSet.Add(item); } return unionSet; } public HashSet Subtract(HashSet set) { HashSet subtractSet = new HashSet(this); if (null == set) { return subtractSet; } foreach (T item in set) { if (!subtractSet.Contains(item)) { continue; } subtractSet.dict.Remove(item); } return subtractSet; } public bool IsSubsetOf(HashSet set) { HashSet setToCompare = set ?? NullSet; foreach (T item in this) { if (!setToCompare.Contains(item)) { return false; } } return true; } public HashSet Intersection(HashSet set) { HashSet intersectionSet = NullSet; if (null == set) { return intersectionSet; } foreach (T item in this) { if (!set.Contains(item)) { continue; } intersectionSet.Add(item); } foreach (T item in set) { if (!Contains(item) || intersectionSet.Contains(item)) { continue; } intersectionSet.Add(item); } return intersectionSet; } public bool IsProperSubsetOf(HashSet set) { HashSet setToCompare = set ?? NullSet; // A is a proper subset of a if the b is a subset of a and a != b return (IsSubsetOf(setToCompare) && !setToCompare.IsSubsetOf(this)); } public bool IsSupersetOf(HashSet set) { HashSet setToCompare = set ?? NullSet; foreach (T item in setToCompare) { if (!Contains(item)) { return false; } } return true; } public bool IsProperSupersetOf(HashSet set) { HashSet 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)); } public List ToList() { return new List(this); } #region Implementation of ISerializable ///  /// Populates a  with the data needed to serialize the target object. ///  /// The  to populate with data. The destination (see ) for this serialization. The caller does not have the required permission.  public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); dict.GetObjectData(info, context); } #endregion #region Implementation of IDeserializationCallback ///  /// Runs when the entire object graph has been deserialized. ///  /// The object that initiated the callback. The functionality for this parameter is not currently implemented.  public void OnDeserialization(object sender) { dict.OnDeserialization(sender); } #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 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 } 

Podría usar Iesi.Collections (utilizado por NHibernate) o el HashSet de Mono

La Biblioteca C5 también tiene una implementación HashSet.

Creo que la biblioteca de PowerCollections debe ajustarse a sus necesidades. Es una biblioteca de código abierto que contiene varias clases de colección que faltaban en .NET, incluyendo Set , Bag , MultiDictionary , etc. Se ejecuta en .NET 2.0. Lo he usado por un par de años y estoy muy contento con él.

Puede alias el diccionario como Hashset con una directiva using. No es realmente lo mismo, pero puede simplificar las cosas para usted más adelante.