C# 提供了多种容器来存放数据,并提供数据的增删改查等功能,容器所实现的接口规范了容器所具有的的行为和能力,下面列举一些 C# 容器相关的接口
1. 接口 IEnumerator
枚举器或迭代器,实现该接口的类可以用来迭代,也就是遍历容器,看源码
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
-
属性Current
返回当前元素 -
方法
MoveNext
将迭代器指针指向下一个元素,并返回下一个元素是否为空 -
方法
Reset
重置迭代器到第一个元素的前方
2. 接口 IEnumerable
实现此接口的类可以被迭代或遍历,看源码
public interface IEnumerable
{
[DispId(-4)]
IEnumerator GetEnumerator();
}
- 只有一个返回迭代器的方法
C# 中的数据容器基本都是可以被遍历的,所以容器类都实现了 IEnumerable
接口,我们通常用 foreach
来遍历容器,foreach
实际上只是一个语法糖,编译时是通过获取容器的迭代器,调用 MoveNext
方法来实现的遍历,例如下面这段代码:
Array a = new int[100];
foreach(int v in a)
{
Debug.Log(v);
}
IEnumerator enumerator = a.GetEnumerator();
while (enumerator.MoveNext())
{
Debug.Log(enumerator.Current);
}
3. 接口 IComparer
实现此接口的类可以进行元素的比较,看源码
public interface IComparer
{
int Compare(object x, object y);
}
我们经常需要对容器中的元素进行排序,那么排序的依据就是一个实现了 IComparer
接口的类对象,例如,Array
容器实现了 IStructuralComparable
接口,该接口的源码是
public interface IStructuralComparable
{
int CompareTo(object other, IComparer comparer);
}
也就是说,Array
容器的元素需要能和其它元素进行比较得出结果,而比较的逻辑由传入的 IComparer
类参数确定
4. 接口 IEqualityComparer
实现此接口的类可以比较元素是否相等,看源码
[ComVisible(true)]
public interface IEqualityComparer
{
bool Equals(object x, object y);
int GetHashCode(object obj);
}
-
方法
Equals
定义两个元素相等性的判断逻辑 -
方法
GetHashCode
定义如何计算元素的 Hash 值
在使用容器时经常需要判断容器中的元素是否相等,这里的相等行为通常是可定制的,可以通过实现 IEqualityComparer
对应的方法来定制比较接口,例如,Array
容器实现了 IStructuralEquatable
接口,该接口的源码是
public interface IStructuralEquatable
{
bool Equals(object other, IEqualityComparer comparer);
int GetHashCode(IEqualityComparer comparer);
}
也就是说,Array
容器的元素可以判定是否和另外一个元素相等,判断逻辑由传入的 IEqualityComparer
参数确定,同样也可以定义元素 Hash 值的计算逻辑
5. 接口 ICloneable
实现此接口的类可以被复制,源码:
public interface ICloneable
{
object Clone();
}
复制的行为完全由 Clone
方法来定义,例如我们可以自己让自己的容器集成 ICloneable
,通过实现 Clone
方法类定义我们的容器被复制时,是深复制还是浅复制
6. 接口 ICollection
此接口是 IEnumerable
的加强接口,所以肯定是能够被迭代遍历的,源码
public interface ICollection : IEnumerable
{
int Count { get; }
bool IsSynchronized { get; }
object SyncRoot { get; }
void CopyTo(Array array, int index);
}
在 IEnumerable
接口的基础上,需提供获取元素数量、复制容器的接口,ICollection
是泛型接口,可以通过泛型参数来实现,如
public interface ICollection<T> : IEnumerable<T>
{
// Number of items in the collections.
int Count { get; }
bool IsReadOnly { get; }
void Add(T item);
void Clear();
bool Contains(T item);
// CopyTo copies a collection into an Array, starting at a particular
// index into the array.
//
void CopyTo(T[] array, int arrayIndex);
//void CopyTo(int sourceIndex, T[] destinationArray, int destinationIndex, int count);
bool Remove(T item);
}
7. 接口 IList
此接口描述列表容器应该具备的能力,看源码:
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);
}
除具备 ICollection
和 IEnumerable
提供的能力外,还包括:
-
通过下标访问元素
-
是否固定大小
-
是否只读
-
向列条添加元素
Add
-
在某位置插入元素
Insert
-
删除元素
Remove
-
删除某个位置的元素
RemoveAt
-
获得某个元素的下标
IndexOf
-
清空列表
Clear
我们平时写代码时,如何选择合适的容器呢?需要考虑
-
存储元素,额外的存储空间
-
添加、插入、删除元素的时间复杂度
-
查找元素的效率
网友评论