C# List<T>源码浅析

所在框架版本:.Net Framework 4.0.30319

1.部分变量

private const int _defaultCapacity = 4;  //默认容量
private T[] _items;    //元素数组
private int _size;   //元素个数
private int _version;  //版本号
[NonSerialized]
private object _syncRoot;  
private static readonly T[] _emptyArray = new T[0];  //空的只读的数组

2.构造函数

public List() => this._items = List<T>._emptyArray;   //如果没有传入初始容量,则给默认只读的空数组
public List(int capacity)   //传入初始容量的情况
    {
      if (capacity < 0)
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
      if (capacity == 0)   //如果传入的容量为0,依旧给默认只读的空数组
        this._items = List<T>._emptyArray;
      else    //否则初始化元素数组
        this._items = new T[capacity];
    }
public List(IEnumerable<T> collection)    //传入集合的情况
    {
      if (collection == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
      if (collection is ICollection<T> objs)  //如果传入的是个泛型集合
      {
        int count = objs.Count;
        if (count == 0)
        {
          this._items = List<T>._emptyArray;
        }
        else
        {
          this._items = new T[count];   //初始化元素数组
          objs.CopyTo(this._items, 0);   //将集合的元素拷贝到数组中
          this._size = count;    //元素个数赋值
        }
      }
      else    //如果传入的是个非泛型集合
      {
        this._size = 0;
        this._items = List<T>._emptyArray;
        foreach (T obj in collection)
          this.Add(obj);    //将元素添加进数组
      }
    }

3.属性

public int Capacity    //容量,可读可写
    {
      [__DynamicallyInvokable] get => this._items.Length;
      [__DynamicallyInvokable] set
      {
        if (value < this._size)
          ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
        if (value == this._items.Length)   //如果传入的和元素数组长度相等,不做处理
          return;
        if (value > 0)
        {
          T[] objArray = new T[value];     //新建一个传入长度的数组
          if (this._size > 0)       //如果已有的元素个数大于0
            Array.Copy((Array) this._items, 0, (Array) objArray, 0, this._size);   //将原数组的元素拷贝到新的数组中
          this._items = objArray;    //重新赋值
        }
        else
          this._items = List<T>._emptyArray;    //重新给空数组
      }
    }
public int Count    //列表长度,只读
    {
      [__DynamicallyInvokable] get => this._size;   //返回元素个数
    }
public T this[int index]    //获取或设置指定索引处的元素
    {
      [__DynamicallyInvokable] get
      {
        if ((uint) index >= (uint) this._size)       //如果索引大于当前元素个数,抛出异常
          ThrowHelper.ThrowArgumentOutOfRangeException();
        return this._items[index];   
      }
      [__DynamicallyInvokable] set
      {
        if ((uint) index >= (uint) this._size)
          ThrowHelper.ThrowArgumentOutOfRangeException();
        this._items[index] = value;     设置对应元素
        ++this._version;  //版本号更新
      }
    }

4.添加元素

public void Add(T item)  
    {
      if (this._size == this._items.Length)    //如果已满,则扩容
        this.EnsureCapacity(this._size + 1);   
      this._items[this._size++] = item;     //否则将元素添加到数组中
      ++this._version;  //版本号更新
    }
public void AddRange(IEnumerable<T> collection) => this.InsertRange(this._size, collection);    //将指定集合的元素添加到末尾


public void InsertRange(int index, IEnumerable<T> collection)     
    {
      if (collection == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
      if ((uint) index > (uint) this._size)
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
      if (collection is ICollection<T> objs)   //如果是个泛型集合
      {
        int count = objs.Count;      //获得传入集合的元素个数
        if (count > 0)
        {
          this.EnsureCapacity(this._size + count);    //如果插入的元素个数大于0,则扩容
          if (index < this._size)    //插入位置小于当前元素数
            Array.Copy((Array) this._items, index, (Array) this._items, index + count, this._size - index);  //将插入位置后的所有元素移动到插入数量之后,空出一段位置
          if (this == objs)   //如果列表和参数集合是同一个
          {
            Array.Copy((Array) this._items, 0, (Array) this._items, index, index);
            Array.Copy((Array) this._items, index + count, (Array) this._items, index * 2, this._size - index);   //自己拼接自己就好
          }
          else     //如果不同
          {
            T[] array = new T[count];   //新建一个长度为参数集合长度的数组
            objs.CopyTo(array, 0);    //将参数集合拷贝到数组中
            array.CopyTo((Array) this._items, index);   //再将数组拷贝到列表中
          }
          this._size += count;    //元素个数更新
        }
      }
      else    //如果不是个泛型集合
      {
        foreach (T obj in collection)
          this.Insert(index++, obj);     //插入到列表中
      }
      ++this._version;   //版本号更新
    }

5.扩容

private void EnsureCapacity(int min) 
    {
      if (this._items.Length >= min)    //如果列表的容量大于传入的参数,不做处理
        return;
      int num = this._items.Length == 0 ? 4 : this._items.Length * 2;  //判断目前列表的容量是否为0,如果是,给最小的容量4,否则扩展到当前容量的两倍
      if ((uint) num > 2146435071U)   //限制,防止溢出
        num = 2146435071;
      if (num < min)   
        num = min;
      this.Capacity = num;   //给到容量
    }

6.插入

public void Insert(int index, T item)
    {
      if ((uint) index > (uint) this._size)   //如果索引大于当前元素个数,抛出异常
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
      if (this._size == this._items.Length)   //如果满了,扩容
        this.EnsureCapacity(this._size + 1);
      if (index < this._size)    //如果要插入的位置在列表中
        Array.Copy((Array) this._items, index, (Array) this._items, index + 1, this._size - index);  //插入之后的部分整体往后挪
      this._items[index] = item;   //对应元素插入
      ++this._size;   //元素个数加一
      ++this._version;   //版本号加一
    }

7.查找

public bool Contains(T item)
    {
      if ((object) item == null)   //如果要查找的为空
      {
        for (int index = 0; index < this._size; ++index)   //遍历数组
        {
          if ((object) this._items[index] == null)   //如果找到了空值
            return true;
        }
        return false;
      }
      EqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
      for (int index = 0; index < this._size; ++index)
      {
        if (equalityComparer.Equals(this._items[index], item))   //如果找到了
          return true;
      }
      return false;
    }
public bool Exists(Predicate<T> match) => this.FindIndex(match) != -1;

public int FindIndex(Predicate<T> match) => this.FindIndex(0, this._size, match);

public int FindIndex(int startIndex, Predicate<T> match) => this.FindIndex(startIndex, this._size - startIndex, match);

public int FindIndex(int startIndex, int count, Predicate<T> match)
    {
      if ((uint) startIndex > (uint) this._size)
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
      if (count < 0 || startIndex > this._size - count)
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
      if (match == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
      int num = startIndex + count;
      for (int index = startIndex; index < num; ++index)  //遍历搜索范围
      {
        if (match(this._items[index]))  //看是否有匹配条件的元素
          return index;    //返回下标
      }
      return -1;    //没找到返回-1
    }
public T FindLast(Predicate<T> match)     //搜索与指定谓词所定义的条件相匹配的元素,并返回整个列表中的最后一个匹配元素
    {
      if (match == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
      for (int index = this._size - 1; index >= 0; --index)   //倒过来遍历
      {
        if (match(this._items[index]))
          return this._items[index];
      }
      return default (T);   //找不到返回默认值
    }
    

public int FindLastIndex(Predicate<T> match) => this.FindLastIndex(this._size - 1, this._size, match);

public int FindLastIndex(int startIndex, Predicate<T> match) => this.FindLastIndex(startIndex, startIndex + 1, match);

public int FindLastIndex(int startIndex, int count, Predicate<T> match)
    {
      if (match == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
      if (this._size == 0)
      {
        if (startIndex != -1)
          ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
      }
      else if ((uint) startIndex >= (uint) this._size)
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
      if (count < 0 || startIndex - count + 1 < 0)
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
      int num = startIndex - count;
      for (int index = startIndex; index > num; --index)   //倒过来遍历
      {
        if (match(this._items[index]))
          return index;
      }
      return -1;  //找不到返回-1
    }

8.清除

public bool Remove(T item)
    {
      int index = this.IndexOf(item);   //查找匹配的第一个元素的索引
      if (index < 0)
        return false;
      this.RemoveAt(index);
      return true;
    }
    
public void RemoveAt(int index)
    {
      if ((uint) index >= (uint) this._size)
        ThrowHelper.ThrowArgumentOutOfRangeException();
      --this._size;   //元素个数减一
      if (index < this._size)
        Array.Copy((Array) this._items, index + 1, (Array) this._items, index, this._size - index);   //要移除位置之后的元素全体往前提
      this._items[this._size] = default (T);   //最后一个元素给默认值
      ++this._version;  //版本号加一
    }
    
public int RemoveAll(Predicate<T> match)   //移除与指定的谓词所定义的条件相匹配的所有元素
    {
      if (match == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
      int index1 = 0;   //不匹配索引
      while (index1 < this._size && !match(this._items[index1]))
        ++index1;
      if (index1 >= this._size)
        return 0;
      int index2 = index1 + 1; //匹配索引
      while (index2 < this._size)
      {
        while (index2 < this._size && match(this._items[index2]))
          ++index2;
        if (index2 < this._size)
          this._items[index1++] = this._items[index2++];   //将不匹配元素放在一起
      }
      Array.Clear((Array) this._items, index1, this._size - index1);  //清除所有匹配元素
      int num = this._size - index1;  //移除的元素个数
      this._size = index1;   //元素个数更新
      ++this._version;   //版本号更新
      return num;
    }
    

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 (this._size - index < count)
        ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
      if (count <= 0)
        return;
      int size = this._size;
      this._size -= count;   //移除后的元素个数
      if (index < this._size)
        Array.Copy((Array) this._items, index + count, (Array) this._items, index, this._size - index);  //将不移除的元素前提
      	Array.Clear((Array) this._items, this._size, count);   //剩余元素清除
      ++this._version;   //版本号更新
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值