在C#中模拟类似于hashSet的列表,以便List具有noduplicate值

时间:2010-03-07 14:55:38

标签: c# list

我想在List中添加colections,但前提是广告尚不存在。我知道HashSet的工作原理是没有重复的值,但是使用HashSet我不能使用AddRange和GetRange。

那么可以像hashSet一样模拟List吗?

List<Advertisements> advertisements = new List<Advertisements>();

advertisements.AddRange(NHibernateSession.CreateCriteria<Advertisements>()
.CreateCriteria(AdvertisementsProperties.City.ToString())
.Add(Restrictions.Or(
Restrictions.Like(CitiesProperties.Name.ToString(), text, MatchMode.Anywhere),
Restrictions.Like(CitiesProperties.SlovenianName.ToString(), text, MatchMode.Anywhere)))
.List<Advertisements>());

advertisements.AddRange(NHibernateSession.CreateCriteria<Advertisements>()
.CreateCriteria(AdvertisementsProperties.Area.ToString())
.Add(Restrictions.Or(
Restrictions.Like(AreasProperties.Name.ToString(), text, MatchMode.Anywhere),
Restrictions.Like(AreasProperties.SlovenianName.ToString(), text, MatchMode.Anywhere)))
.List<Advertisements>());

3 个答案:

答案 0 :(得分:15)

要将一大堆项目添加到HashSet AddRange,只需使用:

set.UnionWith(items);

HashSet中的项目未编入索引(它实现为哈希表,不是为基于索引的元素访问而设计的)。如果您确实需要按索引存储项目,则必须使用简单列表并创建自己的Add方法,在将每个元素添加到基础列表之前检查Contains。当然,线性列表不像HashSet那样提供设置操作的效率。

答案 1 :(得分:1)

结帐this post。海报使用扩展方法向HashSet添加“AddRange”功能。

答案 2 :(得分:0)

如果您经常需要混合列表/集合集合功能,则可能需要创建自己的类。它会是这样的:

using System;
using System.Collections;
using System.Collections.Generic;

public class ListSet<T> : IList<T>, ISet<T> // ISet<T> is supported only from .NET 4.0 on
{
    #region Inner collections

    private HashSet<T> _innerSet = new HashSet<T>();
    private List<T> _innerList = new List<T>();

    #endregion

    #region The read methods delegate to the inner collection which is more appropriate and efficient:

    public bool Contains(T item)
    {
        return this._innerSet.Contains(item);
    }

    public int IndexOf(T item)
    {
        return this._innerList.IndexOf(item);
    }

    // TODO: Implement all other read operations

    #endregion

    #region The write methods must keep both inner collections synchronized

    public bool Add(T item)
    {
        bool wasAdded = this._innerSet.Add(item);
        if (wasAdded) this._innerList.Add(item);

        return wasAdded;
    }

    public void AddRange(IEnumerable<T> items)
    {
        foreach (T item in items) this.Add(item);
    }

    public bool Remove(T item)
    {
        if (this._innerSet.Remove(item))
        {
            return this._innerList.Remove(item);
        }

        return false;
    }

    // TODO: Implement all other write operations
    // TODO: Consider implementing roll back mechanisms in exception handlers
    //            when write operations fail

    #endregion
}