I really want to use hashsets in my program. Using a dictionary feels ugly. I'll probably start using VS2008 with .Net 3.5 some day, so my ideal would be that even though I can't (or can I?) use hashsets in VS2005, when I start using .NET 3.5, I don't want to have to change much, if anything, in order to switch to using these hashsets.
我真的想在我的程序中使用hashsets。使用字典感觉很难看。我可能有一天会开始使用VS2008和.Net 3.5,所以我的理想是即使我不能(或者我可以?)在VS2005中使用hashsets,当我开始使用.NET 3.5时,我不想要必须改变很多,如果有的话,以便切换到使用这些hashsets。
I am wondering if anyone is aware of an existing hashset implementation designed with this in mind, or a way to use the 3.5 hashset in VS2005.
我想知道是否有人知道为此设计的现有hashset实现,或者在VS2005中使用3.5 hashset的方法。
23
You can use HashSet
in a 2.0 application now - just reference System.Core.dll and you should be good to go.
您现在可以在2.0应用程序中使用HashSet
Note: This would require you to install the .NET 3.5 framework which is free and separate from Visual Studio. Once you have that installed you will have the new System.Core assembly which contains the HashSet
type. Since the .NET frameworks versions 2.0 - 3.5 all share the same CLR you can use this assembly in your 2.0 application without any issues.
注意:这将要求您安装免费且独立于Visual Studio的.NET 3.5框架。安装完成后,您将拥有包含HashSet
24
Here's one I wrote for 2.0 that uses a Dictionary
这是我为2.0编写的一个内部使用Dictionary
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
}
8
You could use Iesi.Collections (used by NHibernate) or Mono's HashSet
您可以使用Iesi.Collections(由NHibernate使用)或Mono的HashSet
3
The C5 Library also has a HashSet implementation.
C5库还有一个HashSet实现。
2
I think PowerCollections library should fit your needs. It's an open source library that contains several collection classes that were missing in .NET, including Set
, Bag
, MultiDictionary
etc. It runs on .NET 2.0. I've been using it for couple of years now and I'm very pleased with it.
我认为PowerCollections库应该符合您的需求。它是一个开源库,包含.NET中缺少的几个集合类,包括Set
1
You can alias the Dictionary as Hashset with a using directive. Not really the same thing, but it might simplify things for you later.
您可以使用using指令将Dictionary替换为Hashset。不是一回事,但它可能会在以后简化你的事情。