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
投稿

猜你喜欢

  • JAVA操作MongoDB数据库实例教程

    2023-11-18 13:22:27
  • springboot+jersey+tomcat实现跨域方式上传文件到服务器的方式

    2023-08-16 10:26:45
  • java开发中遇到的异常汇总详解

    2023-03-21 02:54:15
  • SpringBoot中Shiro缓存使用Redis、Ehcache的方法

    2023-10-04 17:34:59
  • C# DateTime与时间戳转换实例

    2022-12-12 08:34:12
  • Knife4j 3.0.3 整合SpringBoot 2.6.4的详细过程

    2023-11-25 03:54:34
  • Spring Cloud + Nacos + Seata整合过程(分布式事务解决方案)

    2021-08-31 04:26:52
  • mybatis-plus使用问题小结

    2023-10-30 06:45:58
  • Android中资源文件用法简单示例

    2023-09-24 22:29:04
  • C#实现Windows Form调用R进行绘图与显示的方法

    2021-11-29 05:40:13
  • 浅析C# 状态机Stateless

    2022-03-08 16:39:07
  • Android 8.0如何完美适配全局dialog悬浮窗弹出

    2023-04-09 12:54:00
  • 深入Android MediaPlayer的使用方法详解

    2023-07-21 21:50:47
  • 手把手带你实现一个萌芽版的Spring容器

    2023-03-10 15:45:44
  • SpringBoot使用注解进行分页的实现示例

    2021-08-21 22:45:32
  • android Watchdog 实现剖析

    2022-07-12 06:39:21
  • Java多线程与线程池技术分享

    2021-07-25 07:35:11
  • IDEA内存调试插件(好用)

    2022-04-19 08:51:13
  • Android实现登录界面的注册功能

    2021-10-22 01:17:55
  • Android开发工程中集成mob短信验证码功能的方法

    2022-12-15 06:37:02
  • asp之家 软件编程 m.aspxhome.com