C#集合:ICollection和IList接口

  虽然枚举接口IEnumerable提供了一种向前迭代集合的协议,但是它们并没有提供确定集合大小、根据索引访问成员、搜索以及修改集合的机制。为了实现这些功能,.NET Core定义了ICollectionIListIDictionary接口。这些接口都支持泛型和非泛型版本。然而,非泛型版本的存在只是为了兼容遗留代码。

可以简单总结为:

  • IEnumerable<T>(和IEnumerable):提供了最少的功能支持(仅支持元素枚举)。
  • ICollection<T>(和ICollection):提供一般的功能(例如Count属性)。
  • IList<T>/IDictionary<K, V>及其非泛型版本:支持最多的功能(包括根据索引/键进行“随机”访问)。

ICollection<T>和ICollection

  ICollection<T>是可以对其中的对象进行计数的标准集合接口。它可以确定集合大小(Count),确定集合中是否存在某个元素(Contains),将集合复制到一个数组(ToArray)以及确定集合是否为只读(IsReadOnly)。对于可写集合,还可以对集合元素进行添加(Add)、删除(Remove)以及清空(Clear)操作。由于它扩展自IEnumerable<T>,因此也可以通过foreach语句进行遍历。

public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
    int Count { get; }
    bool IsReadOnly { get; }
    void Add(T item);
    void Clear();
    bool Contains(T item);
    void CopyTo(T[] array, int arrayIndex);
    bool Remove(T item);
}

  非泛型的ICollection也提供了计数的功能,但是它并不支持修改或检查集合元素的功能:

public interface ICollection : IEnumerable
{
    int Count { get; }
    object SyncRoot { get; }
    bool IsSynchronized { get; }
    void CopyTo(Array array, int index);
}

IList<T>和IList

  IList<T>是按照位置对集合进行索引的标准接口。除了从ICollection<T>IEnumerable<T>继承的功能之外,它还可以按位置(通过索引器)读写元素,并在特定位置插入/删除元素。

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
{
    T this[int index] { get; set; }
    int IndexOf(T item);
    void Insert(int index, T item);
    void RemoveAt(int index);
}

  IndexOf方法可以对列表执行线性搜索,如果未找到指定的元素则返回-1。

  IList的非泛型版本具有更多的成员,因为(相比泛型版本)它从ICollection继承过来的成员比较少:

public interface IList : ICollection, IEnumerable
{
    object this[int index] { get; set; }
    bool IsReadOnly { get; }
    bool IsFixedSize { get; }
    int Add(object value);
    void Clear();
    bool Contains(object value);
    int IndexOf(object value);
    void Insert(int index, object value);
    void Remove(object value);
    void RemoveAt(int index);
}

  非泛型的IList接口的Add方法会返回一个整数代表最新添加元素的索引。相反,ICollection<T>Add方法的返回类型为void

  通用的List<T>类实现了IList<T>IList两种接口。C#的数组同样实现了泛型和非泛型版本的IList接口。

IReadOnlyCollection<T>与IReadOnlyList<T>

  .NET Core同样定义了一系列仅提供只读操作的集合及列表接口:

public interface IReadOnlyCollection<out T> : IEnumerable<T>, IEnumerable
{
    int Count { get; }
}
public interface IReadOnlyList<out T> : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
    T this[int index] { get; }
}

  由于上述接口的类型参数仅仅在输出时使用,因此被标记为协变参数。这样我们就可以将一个“猫咪”的列表表示为一个“动物”的只读列表。

  相反,在IList<T>ICollection<T>中,由于T在输入输出时均被使用,因此没有标记为协变参数。

posted @ 2022-08-26 14:01  一纸年华  阅读(1180)  评论(0编辑  收藏  举报