当前位置:  开发笔记 > 编程语言 > 正文

在C#2.0中使用HashSet,与3.5兼容

如何解决《在C#2.0中使用HashSet,与3.5兼容》经验,为你挑选了3个好方法。

我真的想在我的程序中使用hashsets.使用字典感觉很难看.我可能有一天会开始使用VS2008和.Net 3.5,所以我的理想是即使我不能(或者我可以?)在VS2005中使用hashsets,当我开始使用.NET 3.5时,我不想要必须改变很多,如果有的话,以便切换到使用这些hashsets.

我想知道是否有人知道为此设计的现有hashset实现,或者在VS2005中使用3.5 hashset的方法.



1> Chris Dogget..:

这是我为2.0编写的一个内部使用Dictionary 的.它不是3.5 HashSet 的精确匹配,但它为我完成了这项工作.

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
}


@highphilosopher:那是不对的.对于记录,`Dictionary <>`键方法(包括`ConstainsKey`)是散列O(1)实现,非常类似于类似目的的HashSet方法.`ContainsValue`是O(n).Dictionary的目的之一是为键提供高速查找,而不是将索引用作数组.
凯文,谢谢你让我失望:)我不在那个.

2> Andrew Hare..:

HashSet现在可以在2.0应用程序中使用- 只需参考System.Core.dll,您应该很高兴.

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


是的,你可以,但这并不意味着你应该.框架的许可禁止这件事.

3> Mauricio Sch..:

你可以使用Iesi.Collections(由NHibernate使用)或Mono的HashSet

推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有