在C#2.0中使用哈希集,与3.5兼容

在C#2.0中使用哈希集,与3.5兼容,c#,.net,visual-studio-2005,C#,.net,Visual Studio 2005,我真的很想在我的程序中使用哈希集。使用字典感觉很难看。有一天我可能会开始在.NET3.5中使用VS2008,所以我的理想是,即使我不能(或者我可以?)在VS2005中使用,当我开始使用.NET3.5时,我也不想为了切换到使用这些哈希集而做太多的更改 我想知道是否有人知道现有的hashset实现是基于这一点设计的,或者VS2005中使用3.5 hashset的方法。您现在可以在2.0应用程序中使用hashset——只要参考System.Core.dll就可以了 注意:这将要求您安装免费且独立于Vi

我真的很想在我的程序中使用哈希集。使用字典感觉很难看。有一天我可能会开始在.NET3.5中使用VS2008,所以我的理想是,即使我不能(或者我可以?)在VS2005中使用,当我开始使用.NET3.5时,我也不想为了切换到使用这些哈希集而做太多的更改

我想知道是否有人知道现有的hashset实现是基于这一点设计的,或者VS2005中使用3.5 hashset的方法。

您现在可以在2.0应用程序中使用
hashset
——只要参考System.Core.dll就可以了


注意:这将要求您安装免费且独立于Visual Studio的。一旦安装了该组件,您将拥有新的System.Core组件,其中包含
HashSet
类型。由于.NET Framework 2.0-3.5版都共享相同的CLR,因此您可以在2.0应用程序中使用此程序集,而不会出现任何问题。

您可以使用using指令将字典别名为哈希集。其实并不完全一样,但它可能会在以后为您简化一些事情。

我认为这个库应该适合您的需要。它是一个开源库,包含.NET中缺少的几个集合类,包括
Set
Bag
multi-dictionary
等。它运行在.NET 2.0上。我已经使用它好几年了,我对它很满意。

您可以使用(由NHibernate使用)或者也有一个哈希集实现。

这里是我为2.0编写的一个在内部使用字典的程序。它与3.5哈希集并不完全匹配,但它确实适合我

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;

public class HashSet<T> : ICollection<T>, ISerializable, IDeserializationCallback
{
    private readonly Dictionary<T, object> dict;

    public HashSet()
    {
        dict = new Dictionary<T, object>();
    }

    public HashSet(IEnumerable<T> items) : this()
    {
        if (items == null)
        {
            return;
        }

        foreach (T item in items)
        {
            Add(item);
        }
    }

    public HashSet<T> NullSet { get { return new HashSet<T>(); } }

    #region ICollection<T> Members

    public void Add(T item)
    {
        if (null == item)
        {
            throw new ArgumentNullException("item");
        }

        dict[item] = null;
    }

    /// <summary>
    /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
    /// </summary>
    /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
    public void Clear()
    {
        dict.Clear();
    }

    public bool Contains(T item)
    {
        return dict.ContainsKey(item);
    }

    /// <summary>
    /// Copies the items of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
    /// </summary>
    /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the items copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or-<paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.-or-The number of items in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.-or-Type T cannot be cast automatically to the type of the destination <paramref name="array"/>.</exception>
    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);
    }

    /// <summary>
    /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
    /// </summary>
    /// <returns>
    /// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
    /// </returns>
    /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
    public bool Remove(T item)
    {
        return dict.Remove(item);
    }

    /// <summary>
    /// Gets the number of items contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
    /// </summary>
    /// <returns>
    /// The number of items contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
    /// </returns>
    public int Count
    {
        get { return dict.Count; }
    }

    /// <summary>
    /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
    /// </summary>
    /// <returns>
    /// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
    /// </returns>
    public bool IsReadOnly
    {
        get
        {
            return false;
        }
    }

    #endregion

    public HashSet<T> Union(HashSet<T> set)
    {
        HashSet<T> unionSet = new HashSet<T>(this);

        if (null == set)
        {
            return unionSet;
        }

        foreach (T item in set)
        {
            if (unionSet.Contains(item))
            {
                continue;
            }

            unionSet.Add(item);
        }

        return unionSet;
    }

    public HashSet<T> Subtract(HashSet<T> set)
    {
        HashSet<T> subtractSet = new HashSet<T>(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<T> set)
    {
        HashSet<T> setToCompare = set ?? NullSet;

        foreach (T item in this)
        {
            if (!setToCompare.Contains(item))
            {
                return false;
            }
        }

        return true;
    }

    public HashSet<T> Intersection(HashSet<T> set)
    {
        HashSet<T> 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<T> set)
    {
        HashSet<T> 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<T> set)
    {
        HashSet<T> setToCompare = set ?? NullSet;

        foreach (T item in setToCompare)
        {
            if (!Contains(item))
            {
                return false;
            }
        }

        return true;
    }

    public bool IsProperSupersetOf(HashSet<T> set)
    {
        HashSet<T> 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<T> ToList()
    {
        return new List<T>(this);
    }

    #region Implementation of ISerializable

    /// <summary>
    /// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
    /// </summary>
    /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data. </param><param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization. </param><exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (info == null) throw new ArgumentNullException("info");
        dict.GetObjectData(info, context);
    }

    #endregion

    #region Implementation of IDeserializationCallback

    /// <summary>
    /// Runs when the entire object graph has been deserialized.
    /// </summary>
    /// <param name="sender">The object that initiated the callback. The functionality for this parameter is not currently implemented. </param>
    public void OnDeserialization(object sender)
    {
        dict.OnDeserialization(sender);
    }

    #endregion

    #region Implementation of IEnumerable

    /// <summary>
    /// Returns an enumerator that iterates through the collection.
    /// </summary>
    /// <returns>
    /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
    /// </returns>
    /// <filterpriority>1</filterpriority>
    public IEnumerator<T> GetEnumerator()
    {
        return dict.Keys.GetEnumerator();
    }

    /// <summary>
    /// Returns an enumerator that iterates through a collection.
    /// </summary>
    /// <returns>
    /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
    /// </returns>
    /// <filterpriority>2</filterpriority>
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    #endregion
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Runtime.Serialization;
公共类哈希集:ICollection、ISerializable、IDeserializationCallback
{
专用只读词典;
公共哈希集()
{
dict=新字典();
}
公共哈希集(IEnumerable项):this()
{
if(items==null)
{
返回;
}
foreach(项目中的T项目)
{
增加(项目);
}
}
公共HashSet null集{get{return new HashSet();}}
#区域i集合成员
公共作废新增(T项)
{
if(null==项)
{
抛出新的异常(“项”);
}
dict[项目]=空;
}
/// 
///从中删除所有项目。
/// 
///该文件是只读的。
公共空间清除()
{
格言(Clear);
}
公共布尔包含(T项)
{
返回dict.ContainsKey(项目);
}
/// 
///从特定索引开始,将的项复制到。
/// 
///作为从中复制的项的目标的一维。必须具有基于零的索引。从中开始复制的基于零的索引为空。小于0。是多维的。-或-等于或大于长度。-或源中的项数大于从到的可用空间目标。-或类型T无法自动转换为目标的类型。
public void CopyTo(T[]数组,int arrayIndex)
{
如果(array==null)抛出新的ArgumentNullException(“array”);
if(arrayIndex<0 | | arrayIndex>=array.Length | | arrayIndex>=Count)
{
抛出新ArgumentOutOfRangeException(“arrayIndex”);
}
dict.Keys.CopyTo(数组、数组索引);
}
/// 
///从中删除特定对象的第一个引用。
/// 
/// 
///如果已成功从中删除,则为true;否则为false。如果未在原始中找到,则此方法也返回false。
/// 
///要从中删除的对象。是只读的。
公共布尔删除(T项)
{
返回指令删除(项目);
}
/// 
///获取中包含的项目数。
/// 
/// 
///中包含的项目数。
/// 
公共整数计数
{
获取{return dict.Count;}
}
/// 
///获取一个值,该值指示是否为只读。
/// 
/// 
///如果为只读,则为true;否则为false。
/// 
公共图书馆是只读的
{
得到
{
返回false;
}
}
#端区
公共哈希集联合(哈希集)
{
HashSet unionSet=新的HashSet(此);
if(null==set)
{
返回联合集;
}
foreach(集合中的T项)
{
if(unionSet.Contains(项目))
{
继续;
}
unionSet.Add(项目);
}
返回联合集;
}
公共哈希集减法(哈希集)
{
HashSet subtractSet=新的HashSet(此);
if(null==set)
{
返回集;
}
foreach(集合中的T项)
{
如果(!subtractSet.Contains(项目))
{
继续;
}
减法集。dict.Remove(项目);
}
返回集;
}
公共bool IsSubsetOf(哈希集)
{
HashSet setToCompare=set??null集;
foreach(本文件中的T项)
{
如果(!setToCompare.Contains(项))
{
返回false;
}
}
返回true;
}
公共哈希集交集(哈希集)
{
HashSet intersectionSet=null集;
if(null==set)
{
返回交叉集;
}
foreach(本文件中的T项)
{
如果(!set.Contains(项目))
{
继续;
}
交叉集添加(项目);
}
foreach(集合中的T项)
{
如果(!Contains(item)| intersectionSet.Contains(item))
{
继续;
}