C#中List<T>存放元素的工作机制

作者:Darren?Ji 时间:2022-09-29 16:31:23 

List<T>是怎么存放元素?我们扒一段List<T>的一段源码来一窥究竟。

using System;
using System.Diagnostic;
using System.Collections.ObjectModel;
using System.Security.Permissions;

namespace System.Collections.Generic
{
   ...
   [Serializable()]
   public class List<t> : IList<t>, System.Collections.IList
   {
       private const int _defaultCapacity = 4;
       private T[] _items; //List<T>内部是依靠数组_items存放数据的
       private int _size; //数组的长度
       private int _version;
       [NoSerialized]
       private Object _syncRoot;
       static T[] _emptyArray = new T[0];

//无参数构造函数 把_items设置成一个空的数组
       public List()
       {
           _items = _emptyArray;
       }

//此构造函数 给_items数组一个初始容量
       public List(int capacity)
       {
           ...
           items = new T[capaicty];
       }

//此构造函数 把集合类型参数拷贝给_items数组
       public List(IEnumerable<t> collection)
       {
           ...
           ICollection<t> c = collection as ICollection<t>;
           if(c != null)
           {
               int count = c.Count; //把构造函数集合类型参数的长度赋值给临时变量count
               _items = new T[count]; //List<T>内部维护的_items数组的长度和构造函数集合类型参数的长度一致
               c.CopyTo(_items, 0); //把构造函数集合的所有元素拷贝到_items数组中去
               _size = count; //_items数组的长度就是构造函数集合类型参数的长度
           }
           else
           {
               _size = 0;
               _items = new T[_defaultCapacity];
               ...
           }
       }

//通过设置这个属性,改变List<t>内部维护的_items数组的长度
       public int Capacity
       {
           get {return _items.Length; }
           set {
               if(value != _items.Length){ //如果当前赋值和List<t>维护的内部数组_items长度不一致
                   if(value < _size){
                       //TODO: 处理异常
                   }
                   if(value > 0){
                       T[] newItems = new T[value]; //创建一个临时的、新的数组,长度为新的赋值
                       if(_size > 0){
                           //把临时的、新的数组拷贝给List<t>内部维护的数组_items,注意,这时_items的长度为新的赋值
                           Array.Copy(_items, 0, newItems, 0, _size);
                       }
                   } else {
                       _items = _emptyArray;
                   }
               }
           }
       }

public void Add(T item)
       {
           if(_size == _items.Length) EnsureCapacity(_size + 1);
           _items[_size++] = item;
           ...
       }

//确保List<t>内部维护的_items数组的长度至少是给定的值
       //如果_items数组原先的长度比给定的值小,就让_items数组的长度设置为原先的长度的2倍
       privat void EnsureCapacity(int min)
       {
           if(_items.Length < min){
                int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Legnth * 2;
                if(newCapacity < min) newCapacity = min;
                Capacity = newCapacity;
           }
       }

}
}

由此可见,向List<T>中存放元素的大致过程是这样的:

  • List<T>内部维护着一个数组_items,用来存放T类型的元素。

  • 当有新的T类型元素存放进来,即调用Add(T item)方法。

  • Add(T item)方法内部调用EnsureCapacity(int min)方法确保List<T>的Capaicty属性值至少在原先长度上加1,最多是原先长度的2倍。

  • 在给Capacity赋值的过程中,对_items的长度进行了扩容。

  • 扩容后,再把新的T类型元素存放进来。

简单地说:

当有新的元素存放到List<T>中时,List<T>先对其维护的内部数组进行扩容,然后再把新元素放进来。

来源:https://www.cnblogs.com/darrenji/p/3843749.html

标签:C#,List,存放,元素
0
投稿

猜你喜欢

  • c#调用存储过程实现登录界面详解

    2023-01-02 22:03:07
  • Spring集成MyBatis 及Aop分页的实现代码

    2022-01-06 14:30:47
  • SpringCloud eureka(server)微服务集群搭建过程

    2023-05-22 15:08:55
  • Android实现购物车及其他功能的角标

    2021-12-24 10:54:54
  • java时间戳转日期格式的实现代码

    2023-08-07 21:44:31
  • 5种Android数据存储方式汇总

    2023-08-06 06:49:04
  • android系统在静音模式下关闭camera拍照声音的方法

    2021-09-04 00:34:20
  • java单例模式学习示例

    2022-03-29 19:03:41
  • Android编程实现仿QQ发表说说,上传照片及弹出框效果【附demo源码下载】

    2022-10-02 11:59:43
  • HttpServletResponse乱码问题_动力节点Java学院整理

    2021-10-18 17:48:51
  • Android 利用反射+try catch实现sdk按需引入依赖库的方法

    2022-09-19 22:09:08
  • C#自定义处理xml数据类实例

    2022-07-02 11:00:39
  • 完美解决关于禁止ViewPager预加载的相关问题

    2021-07-05 11:50:50
  • Android HttpClient GET或者POST请求基本使用方法

    2021-11-18 04:26:57
  • Java求两集合中元素交集的四种方法对比分析

    2023-08-23 09:24:56
  • Springcloud Nacos基本操作代码实例

    2023-07-07 18:24:22
  • C#与C++ dll之间传递字符串string wchar_t* char* IntPtr问题

    2022-09-16 09:34:53
  • InterProcessMutex实现zookeeper分布式锁原理

    2023-08-11 05:46:43
  • springboot v2.0.3版本多数据源配置方法

    2023-07-27 06:37:57
  • android 版本检测 Android程序的版本检测与更新实现介绍

    2022-12-02 11:27:41
  • asp之家 软件编程 m.aspxhome.com