List variable-length generic list
Source address: Reference Source https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs
Field (intercept part):
private T[] _items;//核心是一个数组
private int _size;//数组长度(有效数据长度)
private int _version;
private const int _defaultCapacity = 4;//默认容量
Function (addition, deletion, modification and query):
Increase: Add
// before adding the new element.
public void Add(T item) {
if (_size == _items.Length) EnsureCapacity(_size + 1);//检查是否要扩容
_items[_size++] = item;//直接添加在末尾,并且长度加一
_version++;
}
// Ensures that the capacity of this list is at least the given minimum
// value. If the currect capacity of the list is less than min, the
// capacity is increased to twice the current capacity or to min,
// whichever is larger.
private void EnsureCapacity(int min) {
if (_items.Length < min) {
//计算新容量,如果当前容量为0使用默认容量(4):否则使用当前容量的两倍
//如果新容量大于Array的限定最大长度,新容量应当为Array的限定长度;
//如果新容量小于传入的最小支持长度,新容量应当为输入的指定长度;
int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
if (newCapacity < min) newCapacity = min;
Capacity = newCapacity;
}
}
Insert: Insert
Core code: Array.Copy(_items, index, _items, index + 1, _size - index); uses Array's Copy to directly copy a whole section of memory;
// Inserts an element into this list at a given index. The size of the list
// is increased by one. If required, the capacity of the list is doubled
// before inserting the new element.
//
public void Insert(int index, T item) {
// Note that insertions at the end are legal.
if ((uint) index > (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
}
Contract.EndContractBlock();
if (_size == _items.Length) EnsureCapacity(_size + 1);
if (index < _size) {
Array.Copy(_items, index, _items, index + 1, _size - index);
}
_items[index] = item;
_size++;
_version++;
}
删:Remove,RemoveAt,RemoveRange
Core code: Array.Copy(_items, index + 1, _items, index, _size - index); Use Array's Copy to directly copy a whole section of memory;
// Removes the element at the given index. The size of the list is
// decreased by one.
//
public bool Remove(T item) {
int index = IndexOf(item);
if (index >= 0) {
RemoveAt(index);
return true;
}
return false;
}
// Removes the element at the given index. The size of the list is
// decreased by one.
//
public void RemoveAt(int index) {
if ((uint)index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Contract.EndContractBlock();
_size--;
if (index < _size) {
Array.Copy(_items, index + 1, _items, index, _size - index);
}
_items[_size] = default(T);
_version++;
}
// Removes a range of elements from this list.
//
public void RemoveRange(int index, int count) {
if (index < 0) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
if (count < 0) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
if (_size - index < count)
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
Contract.EndContractBlock();
if (count > 0) {
int i = _size;
_size -= count;
if (index < _size) {
Array.Copy(_items, index + count, _items, index, _size - index);
}
Array.Clear(_items, _size, count);
_version++;
}
}
Change: List [ index ]
public T this[int index] {
get {
// Following trick can reduce the range check by one
if ((uint) index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Contract.EndContractBlock();
return _items[index];
}
set {
if ((uint) index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Contract.EndContractBlock();
_items[index] = value;
_version++;
}
}
check:
Contians()
// Contains returns true if the specified element is in the List.
// It does a linear, O(n) search. Equality is determined by calling
// item.Equals().
//
public bool Contains(T item) {
if ((Object) item == null) {
for(int i=0; i<_size; i++)
if ((Object) _items[i] == null)
return true;
return false;
}
else {
EqualityComparer<T> c = EqualityComparer<T>.Default;
for(int i=0; i<_size; i++) {
if (c.Equals(_items[i], item)) return true;
}
return false;
}
}
Clear: Clear
// Clears the contents of List.
public void Clear() {
if (_size > 0)
{
Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
_size = 0;
}
_version++;
}
Copy: CopyTo
// Copies a section of this list to the given array at the given index.
//
// The method uses the Array.Copy method to copy the elements.
//
public void CopyTo(int index, T[] array, int arrayIndex, int count) {
if (_size - index < count) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
}
Contract.EndContractBlock();
// Delegate rest of error checking to Array.Copy.
Array.Copy(_items, index, array, arrayIndex, count);
}
public void CopyTo(T[] array, int arrayIndex) {
// Delegate rest of error checking to Array.Copy.
Array.Copy(_items, 0, array, arrayIndex, _size);
}
other:
The basic interface flow of List:
//List<T> 类
public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
{
//这里要实现下列的所有接口
}
//IList<T> 接口
public interface IList<T> : ICollection<T>
{
T this[int index] {
get;
set;
}
int IndexOf(T item);
void Insert(int index, T item);
void RemoveAt(int index);
}
//ICollection<T> 接口 C#集合类的接口
public interface ICollection<T> : IEnumerable<T>
{
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);
}
//IEnumerable<out T> 接口
public interface IEnumerable<out T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
//IEnumerable 接口
public interface IEnumerable
{
IEnumerator GetEnumerator();
}