ICollection和Ilist接口
- 虽然枚举接口定义了可以迭代集合的方法,但是它们并没有定义确定集合元素多少,根据索引访问集合元素、搜索和修改元素等方法。为了实现这些功能,.NET Framework定义了IColleciton、IList、IDictionary等接口,这些接口都有相应的泛型等价物,非泛型的存在只是为了保持向后兼容。这些接口的集成关系如下图所示(在上一节有,但是为了方便又拿下来了):
在这里对他们进行一个总结:
①IEnumerable和IEnumerable<T>
:支持最少的功能,只支持枚举
②ICollection和ICollection<T>
:支持一般的功能,例如count。
③IList和IList<T>
以及IDictionary和IDictionary<T>
:支持的功能最全面,包括根据索引/键实现集合中的元素的随机访问。
提示:但是大多数情况下不需要实现这些接口,我们完全可以使用一个Collection<T>
来代替(见下面的“自定义集合和代码”)。LINQ还提供了一个适合大多数情况的方法。
对于上面的(除了IEnumerable和他的泛型版本)接口来说,泛型和非泛型的差别很大,特别是对于IColleciton,这其中是有历史原因的,由于泛型的出现比较晚,而泛型版本是为了利用泛型的出现而新增的,为此IColleciton并没有实现ICollection<T>
。这对于IList和IDictionary来说也是一样的。当然,在通常情况下,可以同时实现这些接口的泛型和非泛型方法。比如说IList,它的泛型版本不扩展它是因为转换到IList<T>
时会同时出现一个Add<T>(T)和一个Add(object)
方法,可能会使用任一类型的参数来调用Add(object)而编译器不为所动。因为这在编译器理解来说是一种正常的多态行为。
IColleciton<T>
IColleciton<T>
是对象可计数集合的标准接口,他提供了很多功能,比如Count、Contains、将集合复制到一个数组 ToArray以及确定集合是否只读IsReadOnly。对于可写的集合,可能还需要对集合进行Add、Remove、Clear等操作,另外,由于它实现了IEnumerable<T>
,所以可以在实现ICollection<T>
的对象上面执行迭代操作。
public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
int Count { get; }
bool Contains (T item);
void CopyTo (T[] array, int arrayIndex);
bool IsReadOnly { get; }
void Add(T item);
bool Remove (T item);
void Clear();
}
非泛型的ICollection只是相当于是提供了一个可计数的集合,它不支持修改集合或成员的功能。
public interface ICollection : IEnumerable
{
int Count { get; }
bool IsSynchronized { get; }
object SyncRoot { get; }
void CopyTo (Array array, int index);
}
非泛型的版本也考虑了一些线程安全性,而泛型的没有,因为集合已经不存在线程安全的考虑了。
这两个接口都是比较容易实现的,如果要实现一个只读的集合,只需要在Add、Remove、Clear上面抛出异常即可。
这些接口通常与IList和IDictionary一起实现。
IList<T>和IList接口
IList<T>
是标准的可按位置索引接口。除了从ICollectioin<T>和IEnumerable<T>
继承的功能,它还实现了按位置(通过一个索引器)读写元素和按位置插入和删除元素。
public interface IList : ICollection, IEnumerable, IEnumerable
{
T this [int index] { get; set; }
int IndexOf (T item);
void Insert (int index, T item);
void RemoveAt (int index);
}
IndexOf方法可以对列表执行线性搜索,如果没找到结果,会返回-1。
非泛型的IList拥有更多的方法。因为它继承了IColleciton的一些方法:
public interface IList : ICollection, IEnumerable
{
object this [int index] { get; set }
bool IsFixedSize { get; }
bool IsReadOnly { 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方法,会返回一个int类型,表示新添加的元素的索引,相反,ICollection接口上的Add方法返回一个void。
List<T>是IList和IList<T>
的典型实现,C#中的数组也实现了IList和IList<T>
,只是添加和删除元素的功能被显式的实现并在调用的时候会抛出一个异常,也就是说数组其实只是为了实现IList的可索引功能。
IReadOnlyList
这个接口用的少,我以后在写。