【问题标题】:Simple existing implementation of ICollection<T>ICollection<T> 的简单现有实现
【发布时间】:2015-01-31 03:33:53
【问题描述】:

.NET 框架中有ICollection&lt;T&gt; 的简单实现吗? IE。一个能够添加和删除项目但没有索引的集合类。 Collection&lt;T&gt; 绝对不适合,因为它也实现了IList,因此可以通过索引访问元素。

Collection&lt;T&gt;List&lt;T&gt; 公开为ICollection&lt;T&gt; 在我的情况下也不起作用,因为我需要从中继承我自己的类,并且从任何其他实现IList&lt;T&gt; 的类继承的类将具有索引也是。

我知道自己实现一个没什么大不了的,但只是认为它应该已经存在,搜索但没有找到类似的东西。

【问题讨论】:

  • IList 未排序。
  • 同意科里。 IList&lt;T&gt; 只是一个接口。排序需要一个实现; IList&lt;T&gt; 根本没有任何迹象表明它是有序的。添加到 Collection&lt;T&gt; 的项目很可能按照您添加它们的顺序存储。
  • .Net 框架中没有提供真正随机的项目排序的集合...当您说 List-like once 不起作用时,请澄清您在寻找什么,因为它们是“订购”。
  • 我的错误,IList&lt;T&gt; 确实没有订购。但它允许通过索引访问项目,这在我的情况下是不需要的。我不需要随机顺序,只是不允许通过索引访问它。将编辑问题以澄清。
  • 然后用您自己的类覆盖Collection&lt;T&gt;,并短路您不想公开的任何方法。或者,正如 David L. 在下面指出的那样,使用 Collection&lt;T&gt; 创建一个 ICollection&lt;T&gt; 的实例,并且只有 ICollection&lt;T&gt; 中的那些方法将在实例化对象中可用。

标签: c# .net generics


【解决方案1】:

以下是在System.Collections 命名空间中实现ICollection&lt;T&gt; 的类列表:

System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
System.Collections.Generic.Dictionary<TKey, TValue>
System.Collections.Generic.HashSet<T>
System.Collections.Generic.LinkedList<T>
System.Collections.Generic.List<T>
System.Collections.Generic.SortedDictionary<TKey, TValue>
System.Collections.Generic.SortedList<TKey, TValue>
System.Collections.Generic.SortedSet<T>
System.Collections.ObjectModel.Collection<T>
System.Collections.ObjectModel.ReadOnlyCollection<T>
System.Collections.ObjectModel.ReadOnlyDictionary<TKey, TValue>
System.Collections.ObjectModel.WeakReadOnlyCollection<T>

但是所有这些实现都添加了额外的功能,并且由于您想从一个实现继承,但只公开ICollection&lt;T&gt; 方法,因此使用它们中的任何一个都不是一个真正的选择。

您唯一的选择就是实现您自己的。这很容易做到。你只需要包装一个合适的ICollection&lt;T&gt; 实现。这是一个默认使用List&lt;T&gt;,但也允许派生类使用特定类型的ICollection&lt;T&gt;

class SimpleCollection<T> : ICollection<T>
{

    ICollection<T> _items;


    public SimpleCollection() {
        // Default to using a List<T>.
        _items = new List<T>();
    }

    protected SimpleCollection(ICollection<T> collection) {
        // Let derived classes specify the exact type of ICollection<T> to wrap.
        _items = collection;
    }

    public void Add(T item) { 
        _items.Add(item); 
    }

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

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

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

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

    public bool IsReadOnly
    {
        get { return false; }
    }

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

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

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

这超出了您所追求的范围,但是,例如,如果您想要存储独特的项目,您可以从中派生并提供 HashSet&lt;T&gt; 作为要包装的集合类型:

class UniqueCollection<T> : SimpleCollection<T>
{
    public UniqueCollection() : base(new HashSet<T>()) {}
}

【讨论】:

    【解决方案2】:
    Hashset<T> 
    

    如果您希望它是无序且具有唯一值的,应该可以使用。

    See MSDN

    如 cmets 中所述,ICollection&lt;T&gt; 是一个更简单的集合,它是无序的并且允许重复条目。 MSDN

    ICollection<string> unordered = new Collection<string>();
    

    最后,我不知道具有 .Add() / .Remove() 功能而不暴露索引的集合的“简单”本机 .NET 实现。所以,要回答你的问题,你的利基功能看起来你必须自己动手。

    【讨论】:

    • HashSet 是非常具体的集合,它的 Add 可能不需要添加项目...我不会将其用作“简单实现”示例...
    • HashSet&lt;T&gt; 要求每个项目都是唯一的,而ICollection&lt;T&gt; 可能包含重复的项目。
    【解决方案3】:

    只是给出一个快速的区别:

    排序列表

    通过获取键而不是索引是最好的方法,它基于二进制搜索。在内部,它使用两个列表:IList 和 IList。它不使用字典。因此它没有任何哈希值。

    SortedDictionary 与 SortedList 相同。但是,不同的是内部发展。排序字典使用 B 树。因此修改速度很快,查找与排序列表相同。

    HashSet和List的区别在于HashSet保证了唯一性。这意味着如果您尝试将值添加两次,它将忽略该值而不会给出任何错误或重复相同的值。

    因此,如果您不想使用基于索引,则可以使用从 ICollection 继承的 SortedList,然后使用 IEnumerable...

    否则 HashSet 是唯一性很重要的最佳选择。

    【讨论】:

    • SortedList.GetByIndex() 不意味着它仍然基于索引并且可以这样访问,即使首选的访问方法是按键?
    • @DavidL 同意,另外SortedList 可以通过密钥访问,我也不需要。更不用说排序等 - 很多附加功能,绝对不是简单的ICollection 实现的候选者。
    • @DavidL 是的,你是对的。我刚才已经让你清楚地了解了各种选择。如果您只想添加删除,那么您绝对可以使用扩展方法或其他方式,从 ICollection 继承的新子类...
    猜你喜欢
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 2015-09-25
    • 2011-06-14
    • 1970-01-01
    • 2015-03-12
    相关资源
    最近更新 更多