【问题标题】:Unique List<T> in .NET 2.NET 2 中的唯一列表<T>
【发布时间】:2010-02-04 14:18:31
【问题描述】:

什么是

  • 最好是通用的;
  • 独特(IComparable/IEquitable)有价值

.NET 2 的对象集合

à la List&lt;T&gt;,或 .NET 3.5 中的 HashSet&lt;T&gt; 等效项,但没有订购项目)

【问题讨论】:

  • 你为什么在你的问题中加上“à la List&lt;T&gt;”?这不是一个独特的项目列表。
  • 如果你是一个邪恶的 h4x0r,你可以在你的应用程序中推出单个 System.Core.dll 程序集。无需安装完整的 .NET 3.5 框架。
  • @serhio - 您只需要安装 .NET 3.5 即可获得 System.Core.dll 的副本,一旦获得副本,您只需添加对该文件的引用并将其与您的应用程序捆绑在一起。
  • HasSet 现在没有.AsReadOnly() 方法... :)

标签: .net collections .net-2.0 unique


【解决方案1】:

不幸的是,第一个很好的框架类是 HashSet,您只能通过 .Net 3.5 访问它。

如果您停留在以前的版本中,那么选项就不那么好了。最常见的是使用 Dictionary 类型,其中 Key 是您尝试存储的值。你可以很容易地将它封装在你自己的类中。

如果你愿意一起跳出框架,有.Net的数据结构集合,比如NGenerics

【讨论】:

  • 谢谢。我使用 System.Collections.Generic.Dictionary 来获得我需要的效果。我把它包装在一个 try/catch(ArgumentException)
  • .Net 4.0 中是否有任何唯一队列,例如如果队列 在任何级别包含 1 并且尝试再次添加 1 应该会引发错误。
  • @MubasharAhmad 不,这不是一个常见的要求,可能永远不会添加到框架中。您始终可以通过同时拥有 Queue 和 HashSet 来创建此行为,然后在任何操作上更新两者。
【解决方案2】:

你需要的是一个 Set,据我记得 2.0 中没有 Set 实现。您可以查看this

编辑:如果你真的想实现自己的,这样的事情会以牺牲插入性能为代价来完成这项工作:(我没有测试功能)

class UniqueList<T> : IList<T>
{
    private IList<T> m_InternalList;

    public UniqueList(IList<T> list)
    {
        m_InternalList = list;
    }

    public System.Collections.ObjectModel.ReadOnlyCollection<T> AsReadOnly()
    {
        return new System.Collections.ObjectModel.ReadOnlyCollection<T>(this);
    }

    #region IList<T> Members

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

    public void Insert(int index, T item)
    {
        if (!m_InternalList.Contains(item))
            m_InternalList.Insert(index, item);
    }

    public void RemoveAt(int index)
    {
        m_InternalList.RemoveAt(index);
    }

    public T this[int index]
    {
        get
        {
            return m_InternalList[index];
        }
        set
        {
            if (!m_InternalList.Contains(value))
                m_InternalList[index] = value;
        }
    }

    #endregion

    #region ICollection<T> Members

    public void Add(T item)
    {
        if (!m_InternalList.Contains(item))
            m_InternalList.Add(item);
    }

    public void Clear()
    {
        m_InternalList.Clear();
    }

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

    public void CopyTo(T[] array, int arrayIndex)
    {
        m_InternalList.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return m_InternalList.Count; }
    }

    public bool IsReadOnly
    {
        get { return m_InternalList.IsReadOnly; }
    }

    public bool Remove(T item)
    {
        return m_InternalList.Remove(item);
    }

    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
        return m_InternalList.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return m_InternalList.GetEnumerator();
    }

    #endregion
}

【讨论】:

  • 对于我来说,导入一个“外部”项目只是为了一个独特的集合,这是一个有点“硬”的解决方案。我更喜欢或自己编写一个自定义集合,或者更好的解决方案只是在现有框架类上使用“技巧”。
  • @serhio:我认为编写自己的集合类比仅引用已被证明有效的 3rd 方组件“更难”。我认为您患有“不是在这里发明”综合症。 :)
  • 我真正需要的一种方法是.AsReadOnly()
【解决方案3】:

您可以使用在Iesi.Collections 程序集中定义的HashedSet&lt;T&gt; 集合。 这是一个开源项目,NHibernate 也使用它。

【讨论】:

    【解决方案4】:

    我们曾经在 .NET 2 中使用PowerCollections Set 类。它工作得很好。图书馆里有很多好东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-30
      • 2020-05-10
      • 2017-08-30
      • 1970-01-01
      相关资源
      最近更新 更多