https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646
将泛型数据(对值类型来说就是数据本身,对引用类型来说就是引用)存储在一个泛型数组中,添加元素时若超过当前泛型数组容量,则以2倍扩容,进而实现List
public class List : IList, System.Collections.IList, IReadOnlyList
{//继承了IList接口
private const int _defaultCapacity = 4;//默认大小为4
private T[] _items;//泛型数组,数据实际存储在这里
[ContractPublicPropertyName("Count")]
private int _size;//当前List中的元素个数,即Count
private int _version;//版本号,在遍历时如果发现_version变了立即退出并抛出遍历过程集合被修改异常,比如在foreach里remove或add元素就会导致这个异常。更常见的是出现在多线程时一个线程遍历集合,另一个线程修改集合的时候
//每次改变数组,版本号都会加1
[NonSerialized]
private Object _syncRoot;
static readonly T[] _emptyArray = new T[0];
}
public List()//构造器,初始化时容量为0。例如,List list=new List();
{
_items = _emptyArray;
}
public List(int capacity)//构造器,初始化时指定容量,例如List list = new List(10);
{
if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
Contract.EndContractBlock();//输入的capacity不能为负
if (capacity == 0)
_items = _emptyArray;
else
_items = new T[capacity];//分配容量为capacity的连续地址
}
public List(IEnumerable collection)//构造器,将集合中的元素复制到List中,例如List list=new List(new int[3]{1,2,3})
{
if (collection == null)//集合不能为空
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
Contract.EndContractBlock();
ICollection c = collection as ICollection;//将IEnumerable转换为ICollection
if (c != null)
{
int count = c.Count;
if (count == 0)
{
_items = _emptyArray;
}
else
{
_items = new T[count];//分配和集合元素个数相同的容量
c.CopyTo(_items, 0);//该集合意实现了ICollection中的void CopyTo(T[] array, int arrayIndex)方法
_size = count;
}
}
else
{
_size = 0;
_items = _emptyArray;
using (IEnumerator en = collection.GetEnumerator())
{
while (en.MoveNext())
{
Add(en.Current);
}
}
}
}
public int Capacity//属性,获取当前List的容量大小,设置容量大小时List中的数据被复制到新开辟的泛型数组内,复杂度O(n)
//实际扩容操作是在set方法中
{
get
{
Contract.Ensures(Contract.Result() >= 0);
return _items.Length;
}
set
{
if (value < _size)//设置的value要大于当前数组中的元素个数
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
}
Contract.EndContractBlock();
if (value != _items.Length)
{
if (value > 0)
{
T[] newItems = new T[value];
if (_size > 0)
{
Array.Copy(_items, 0, newItems, 0, _size);//这意味着每次扩容要花费O(n)的时间,若估算问题中元素个数在10~15之间,应在初始化List大小而不用默认大小
}
_items = newItems;
}
else
{
_items = _emptyArray;
}
}
}
}
public int Count//只读属性属性,获取当前List中的元素个数
{
get
{
Contract.Ensures(Contract.Result() >= 0);
return _size;
}
}
public void Add(T item)//每次添加的元素在当前泛型数组的末尾,如果元素个数超出泛型数组容量,则扩容
//不扩容时复杂度O(1),扩容时O(n), 分摊O(1)
{
if (_size == _items.Length) EnsureCapacity(_size + 1);
_items[_size++] = item;
_version++;
}
private void EnsureCapacity(int min)//扩容方式,初始长度为0时添加了一个元素,则设置容量为默认容量4,往后以2倍的形式扩容
{ //min表示当前所有元素需要的最小容量
if (_items.Length < min)
{
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;//这行代码主要是添加集合AddRange时判断用,仅Add时可以去掉
Capacity = newCapacity;//设置Capactity属性,在此进行了实际的扩容操作
}
}
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 c = EqualityComparer.Default;
for (int i = 0; i < _size; i++)//遍历数组查找,O(n)时间
{
if (c.Equals(_items[i], item)) return true;//使用相等比较器来判断两元素是否相等,若类型 T 实现 IEquatable 泛型接口,
//则相等比较器是该接口的 Equals(T) 方法;否则,将使用默认的相等比较器Object.Equals(Object)
//Object.Equals(Object)等效于调用 Object.ReferenceEquals,会判断引用是否相等。
}
return false;
}
}
public bool Remove(T item)//复杂度O(n)
{
int index = IndexOf(item);//查找该元素要线性搜索,O(n)
if (index >= 0)
{
RemoveAt(index);
return true;
}
return false;
}
public void RemoveAt(int index)
{
if ((uint)index >= (uint)_size)//输入的索引不能大于元素个数
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Contract.EndContractBlock();
_size--;//元素个数减1
if (index < _size)//判断是否移除了最后一个元素
{
Array.Copy(_items, index + 1, _items, index, _size - index);//将后面的元素前移,复杂度为O(n)
}
_items[_size] = default(T);//最后一个元素恢复默认值
_version++;
}
public int IndexOf(T item)//查找元素索引,返回第一个符合的元素的索引
{ //从0位置开始查找
Contract.Ensures(Contract.Result() >= -1);
Contract.Ensures(Contract.Result() < Count);
return Array.IndexOf(_items, item, 0, _size);
}
public void Clear()//清空列表,把_size赋值为0就可以,重新添加元素时,元素在数组中的位置由_size决定
{
if (_size > 0)
{
Array.Clear(_items, 0, _size); //这行代码不是必须的,其作用是清除元素以便gc可以回收引用
_size = 0;
}
_version++;
}
public void CopyTo(T[] array)//将List中的元素转到数组array中,实现调用了Array.Copy()
{
CopyTo(array, 0);
}
public void CopyTo(T[] array, int arrayIndex)
{
Array.Copy(_items, 0, array, arrayIndex, _size);//从_items的0位置处复制_size个元素放到array中,在arrayIndex处开始放置
}
public T this[int index]//索引器,实现IList接口中的方法,本质上是GetValue(int index),SetValue(Object value,int index)方法
{
get
{
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++;
}
}
public void Insert(int index, T item)//将一个元素插入到index处,原来index处的元素后移
{
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); //原来index处的元素后移,复杂度O(n)
}
_items[index] = item;
_size++;
_version++;
}
public void InsertRange(int index, IEnumerable collection)//将集合中的元素插入List指定索引处
{
if (collection == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
}
if ((uint)index > (uint)_size)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
}
Contract.EndContractBlock();
ICollection c = collection as ICollection;
if (c != null)
{ // if collection is ICollection
int count = c.Count;
if (count > 0)
{
EnsureCapacity(_size + count);//涉及扩容
if (index < _size)//把原来数组中index到index+count的元素后移
{
Array.Copy(_items, index, _items, index + count, _size - index);
}
// If we're inserting a List into itself, we want to be able to deal with that.
if (this == c)
{
// Copy first part of _items to insert location
Array.Copy(_items, 0, _items, index, index);
// Copy last part of _items back to inserted location
Array.Copy(_items, index + count, _items, index * 2, _size - index);
}
else
{
T[] itemsToInsert = new T[count];
c.CopyTo(itemsToInsert, 0);//先把集合中的元素复制到一个数组中
itemsToInsert.CopyTo(_items, index);//再将数组中的元素复制到泛型数组中,从index的位置开始
}
_size += count;
}
}
else
{
using (IEnumerator en = collection.GetEnumerator())
{
while (en.MoveNext())
{
Insert(index++, en.Current);
}
}
}
_version++;
}
public void AddRange(IEnumerable collection)
{
Contract.Ensures(Count >= Contract.OldValue(Count));
InsertRange(_size, collection);
}
public int IndexOf(T item)//查找元素索引,返回第一个符合的元素的索引
{ //从0位置开始查找
Contract.Ensures(Contract.Result() >= -1);
Contract.Ensures(Contract.Result() < Count);
return Array.IndexOf(_items, item, 0, _size);
}
public int IndexOf(T item, int index)//查找元素,从index开始查找
{
if (index > _size)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
Contract.Ensures(Contract.Result() >= -1);
Contract.Ensures(Contract.Result() < Count);
Contract.EndContractBlock();
return Array.IndexOf(_items, item, index, _size - index);
}
public int IndexOf(T item, int index, int count)//查找元素,从index开始,只查找count个元素
{
if (index > _size)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
if (count < 0 || index > _size - count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
Contract.Ensures(Contract.Result() >= -1);
Contract.Ensures(Contract.Result() < Count);
Contract.EndContractBlock();
return Array.IndexOf(_items, item, index, count);
}
public T[] ToArray()
{
Contract.Ensures(Contract.Result() != null);
Contract.Ensures(Contract.Result().Length == Count);
T[] array = new T[_size];
Array.Copy(_items, 0, array, 0, _size);
return array;
}
public void Sort()//排序使用默认比较器Array.Sort
{
Sort(0, Count, null);
}
public void Sort(IComparer comparer)//实现IComparer泛型接口,即实现int Compare(T x, T y);
{
Sort(0, Count, comparer);
}
public void Sort(int index, int count, IComparer comparer)//对列表中从index开始的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();
Array.Sort(_items, index, count, comparer);
_version++;
}
public void Sort(Comparison comparison)//使用委托作为比较器 public delegate int Comparison(T x, T y);
{
if (comparison == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
Contract.EndContractBlock();
if (_size > 0)
{
IComparer comparer = new Array.FunctorComparer(comparison);
Array.Sort(_items, 0, _size, comparer);
}
}
public void Reverse()
{
Reverse(0, Count);
}
public void Reverse(int index, int count)//将从index开始的Count个元素反转,实际调用了Array.Reverse,复杂度O(n)
{
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();
Array.Reverse(_items, index, count);
_version++;
}
public struct Enumerator : IEnumerator, System.Collections.IEnumerator
{
private List list;
private int index;
private int version;
private T current;//获取枚举数当前位置的元素
internal Enumerator(List list)
{
this.list = list;
index = 0;//枚举定位在集合中的第一个元素
version = list._version;//记录当前集合中的版本号
current = default(T);//当前元素为默认值
}
public void Dispose()//释放 List.Enumerator 使用的所有资源
{
}
public bool MoveNext()//使枚举数前进到 List 的下一个元素
{//如果 MoveNext 越过集合的末尾(即index=localList._size),则枚举器将定位到集合中的最后一个元素之后,MoveNext 返回 false
//此时无法将 Current 设置为集合的第一个元素;必须改为创建新的枚举器实例
List localList = list;
if (version == localList._version && ((uint)index < (uint)localList._size))//判断版本号是否改变
{
current = localList._items[index];
index++;
return true;
}
return MoveNextRare();
}
private bool MoveNextRare()
{
if (version != list._version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = list._size + 1;
current = default(T);
return false;
}
public T Current
{
get
{
return current;
}
}
Object IEnumerator.Current//在调用 Current 之前,MoveNext 返回相同的对象。 MoveNext 将 Current 设置为下一个元素
{
get
{
if (index == 0 || index == list._size + 1)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
}
return Current;
}
}
void IEnumerator.Reset()//重置,恢复复默认值
{
if (version != list._version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = 0;
current = default(T);
}
}
MSDN