【C#知识点详解】List<T>储存结构详解

news2025/4/13 4:48:13

        今天来介绍一下List内部的存储结构,话不多说直接开始。

内部数据

        List内部采用了连续数组的方式存储数据,其中包含了三个重要的成员变量,示例如下:

// 用于存储数据的数组
internal T[] _items;
// 列表中实际包含数据的数量
internal int _size;
// 版本号,用于迭代时检测是否修改
internal int _version;
  • T[] _items:存储数据的数组,实际存储数据的地方。
  • int _size:实际包含数据的数量,用于记录_items实际存储数据的数量。
  • int _version:版本号,List迭代时用于检测_items是否被修改。

        

数据操作

        添加数据

        List添加数据是在数据队列尾部进行添加(不是数组尾部),添加时会对_size计数进行增加,示例代码如下:

public void Add(T item)
{
    _version++;
    T[] array = _items;
    int size = _size;
    if ((uint)size < (uint)array.Length)
    {
        _size = size + 1;
        array[size] = item;
    }
}

        当_items容积不够时,List会进行扩容,默认会扩容到原来的2倍。然后会创建一个新的newItems数组,并将原先的_items数据拷贝进去,示例代码如下:

internal void Grow(int capacity)
{
    int newCapacity = _items.Length == 0 ? DefaultCapacity : 2 * _items.Length;

    if ((uint)newCapacity > Array.MaxLength) 
		newCapacity = Array.MaxLength;

    if (newCapacity < capacity) 
		newCapacity = capacity;

    Capacity = newCapacity;
}

public int Capacity
{
    get => _items.Length;
    set
    {
        if (value != _items.Length)
        {
            if (value > 0)
            {
                T[] newItems = new T[value];
                if (_size > 0)
                {
                    Array.Copy(_items, newItems, _size);
                }
                _items = newItems;
            }
        }
    }
}

        

        移除数据

        List在移除数据的时候较常用的两个方法是Remove(T item)RemoveAt(int index)Remove()的执行过程也是先找到数据所在位置的索引,然后在调用RemoveAt()方法,示例代码如下:

public bool Remove(T item)
{
    int index = IndexOf(item);
    if (index >= 0)
    {
        RemoveAt(index);
        return true;
    }

    return false;
}

        RemoveAt()的执行过程是将索引后的数据拷贝前移,拷贝完成后再将最后一位设置成默认值,示例代码如下:

public void RemoveAt(int index)
{
    _size--;
    if (index < _size)
    {
        Array.Copy(_items, index + 1, _items, index, _size - index);
    }
    if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
    {
        _items[_size] = default!;
    }
    _version++;
}

        

        插入数据

        List在插入数据时会调用Insert(int index, T item)接口,插入数据的执行过程与移除数据比较相似,插入数据是将索引位置的数据拷贝后移,然后将索引位置进行赋值,示例代码如下:

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);
    }
    if (_size == _items.Length) Grow(_size + 1);
    if (index < _size)
    {
        Array.Copy(_items, index, _items, index + 1, _size - index);
    }
    _items[index] = item;
    _size++;
    _version++;
}

        

        访问数据

        在List中访问数据最常用的方式是索引访问,通过this[int index]直接获取修改数据。由于数据存储在_items数组中,访问数据时唯一需要注意的只有越界问题。示例代码如下:

public T this[int index]
{
    get
    {
        // Following trick can reduce the range check by one
        if ((uint)index >= (uint)_size)
        {
            ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException();
        }
        return _items[index];
    }

    set
    {
        if ((uint)index >= (uint)_size)
        {
            ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException();
        }
        _items[index] = value;
        _version++;
    }
}

使用场景

        基于前面对List的介绍,List的使用场景可以归纳如下:

  • List提供了灵活的数组存储空间,当数组元素数量不确定时可以选择List。
  • List有较为灵活的数据访问机制,通过索引值即可访问数据,在需要随机访问数据时可以选择List。
  • List存储的数据为连续的数组空间,在遍历数据时有较快的速度。
  • List存储的数据为连续的数组空间,在频繁的添加/移除数据时,建议使用Add(T item)RemoveAt(int lastIndex)方法,这两个方法是在数组尾部进行的数据操作。
  • List存储的数据为连续的数组空间,在调用Insert(int index, T item)RemoveAt(int index)方法插入/移除数据时,会进行数组数据的拷贝,所以不建议高频使用。需要高频在头部/中间插入/删除数据时可以使用LinkedList<T>。

相关文档链接

List官方文档:https://learn.microsoft.com/zh-cn/dotnet/api/system.collections.generic.list-1?view=net-9.0

List源码地址:

https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过AWS EKS 生成并部署容器化应用

今天给大家分享一个实战例子&#xff0c;如何在EKS上创建容器化应用并通过ALB来发布。先介绍一下几个基本概念&#xff1a; IAM, OpenID Connect (OIDC) 2014 年&#xff0c;AWS Identity and Access Management 增加了使用 OpenID Connect (OIDC) 的联合身份支持。此功能允许…

nginx入门,部署静态资源,反向代理,负载均衡使用

Nginx在linux上部署静态资源 概念介绍 Nginx可以作为静态web服务器来部署静态资源。这里所说的静态资源是指在服务端真实存在&#xff0c;并且能够直接展示的一些文件&#xff0c;比如常见的html页面、css文件、js文件、图片、视频等资源。 相对于Tomcat&#xff0c;Nginx处理…

智膳优选 | AI赋能的智慧食堂管理专家 —— 基于飞书多维表格和扣子(Coze)的智能解决方案

智膳优选 | AI赋能的智慧食堂管理专家 基于飞书多维表格和扣子&#xff08;Coze&#xff09;的智能解决方案 数据驱动餐饮管理&#xff0c;让每一餐都是营养与经济的完美平衡&#xff01; “智膳优选”通过整合飞书与Coze&#xff0c;将数据智能引入校园餐饮管理&#xff0…

最新的es版本忘记密码,重置密码

刚刚安装了最新的es版本,就忘了密码,怎么重置密码呢? 一、进入es的斌目录 #进入es文件/bin 目录 ./elasticsearch-reset-password -u elastic 二 、输入对应的密码 然后再次访问 我的是去掉了ssl的访问 三、如果报错:解决 [main] WARN

Compose Multiplatform+Kotlin Multiplatfrom 第五弹跨平台 截图

截图功能 Compose MultiplatformKotlin Multiplatfrom下实现桌面端的截图功能&#xff0c;起码搞了两星期&#xff0c;最后终于做出来了&#xff0c;操作都很流畅&#xff0c;截取的文件大小也正常&#xff0c;可参考支持讨论&#xff01; 功能效果 代码实现 //在jvmMain下创…

Elasticearch数据流向

Elasticearch数据流向 数据流向图 --- config: layout: elk look: classic theme: mc --- flowchart LR subgraph s1["图例"] direction TB W["写入流程"] R["读取流程"] end A["Logstash Pipeline"] -- 写入请求 --> B["Elas…

在docker里装rocketmq-console

首先要到github下载&#xff08;这个一般是需要你有梯子&#xff09; GitHub - apache/rocketmq-externals at release-rocketmq-console-1.0.0 如果没有梯子&#xff0c;用下面这个百度网盘链接下 http://链接: https://pan.baidu.com/s/1x8WQVmaOBjTjss-3g01UPQ 提取码: fu…

使用Python写入JSON、XML和YAML数据到Excel文件

在当今数据驱动的技术生态中&#xff0c;JSON、XML和YAML作为主流结构化数据格式&#xff0c;因其层次化表达能力和跨平台兼容性&#xff0c;已成为系统间数据交换的通用载体。然而&#xff0c;当需要将这类半结构化数据转化为具备直观可视化、动态计算和协作共享特性的载体时&…

x-cmd install | Slumber - 告别繁琐,拥抱高效的终端 HTTP 客户端

目录 核心优势&#xff0c;一览无遗安装应用场景&#xff0c;无限可能示例告别 GUI&#xff0c;拥抱终端 还在为调试 API 接口&#xff0c;发送 HTTP 请求而苦恼吗&#xff1f;还在各种 GUI 工具之间切换&#xff0c;只为了发送一个简单的请求吗&#xff1f;现在&#xff0c;有…

apijson 快速上手

apijson是强大的工具&#xff0c;简化了CRUD的操作&#xff0c;只要有数据库表&#xff0c;就能自动生成RESTFUL接口。但初次上手也是摸索了很长时间&#xff0c;尤其是部署与使用上&#xff0c;这里尝试以初学者角度来说下&#xff1a; 一、好处 1、对于简单的应用&#xff…

3D激光轮廓仪知识整理

文章目录 1.原理和应用场景1.1 相机原理1.1.1 测量原理1.1.2 相机激光器1.1.3 沙姆镜头1.1.4 相机标定1.1.5 中心线提取 1.2 应用场景1.2.1 测量相关应用1.2.2 缺陷检测相关应用 2.相机参数介绍及选型介绍2.1 成像原理2.2 原始图成像2.3 生成轮廓图2.4 相机规格参数2.4.1 单轮廓…

Stable Diffusion+Pyqt5: 实现图像生成与管理界面(带保存 + 历史记录 + 删除功能)——我的实验记录(结尾附系统效果图)

目录 &#x1f9e0; 前言 &#x1f9fe; 我的需求 &#x1f527; 实现过程&#xff08;按功能一步步来&#xff09; &#x1f6b6;‍♂️ Step 1&#xff1a;基本图像生成界面 &#x1f5c3;️ Step 2&#xff1a;保存图片并显示历史记录 &#x1f4cf; Step 3&#xff1a…

使用WasmEdge将InternLM集成到Obsidian,打造本地智能笔记助手

本文来自社区投稿&#xff0c;作者Miley Fu&#xff0c;WasmEdge Runtime 创始成员。 本文将介绍如何通过 WasmEdge 将书生浦语&#xff08;InternLM&#xff09;大模型部署在本地&#xff0c;并与 Obsidian 笔记软件集成&#xff0c;从而在笔记软件中直接利用大模型实现文本总…

java导入excel更新设备经纬度度数或者度分秒

文章目录 一、背景介绍二、页面效果三、代码0.pom.xml1.ImportDevice.vue2.ImportDeviceError.vue3.system.js4.DeviceManageControl5.DeviceManageUserControl6.Repeater7.FileUtils8.ResponseModel9.EnumLongitudeLatitude10.词条 四、注意点本人其他相关文章链接 一、背景介…

视频设备轨迹回放平台EasyCVR远程监控体系落地筑牢国土监管防线

一、背景概述 我国土地资源遭违法滥用的现象愈发严峻&#xff0c;各类土地不合理利用问题频发。不当的土地开发不仅加剧了地质危害风险&#xff0c;导致良田受损、森林资源的滥伐&#xff0c;还引发了煤矿无序开采、城市开发区违建等乱象&#xff0c;给国家宝贵的土地资源造成…

Stable Diffusion 四重调参优化——项目学习记录

学习记录还原&#xff1a;在本次实验中&#xff0c;我基于 Stable Diffusion v1.5模型&#xff0c;通过一系列优化方法提升生成图像的质量&#xff0c;最终实现了图像质量的显著提升。实验从基础的 Img2Img 技术入手&#xff0c;逐步推进到参数微调、DreamShaper 模型和 Contro…

我可能用到的网站和软件

我可能用到的网站和软件 程序员交流的网站代码管理工具前端组件库前端框架在线工具人工智能问答工具学习的网站Windows系统电脑的常用工具 程序员交流的网站 csdn博客博客园 - 开发者的网上家园InfoQ - 软件开发及相关领域-极客邦掘金 (juejin.cn) 代码管理工具 GitHub 有时…

FPGA状态机设计:流水灯实现、Modelsim仿真、HDLBits练习

一、状态机思想 1.概念 状态机&#xff08;Finite State Machine, FSM&#xff09;是计算机科学和工程领域中的一种抽象模型&#xff0c;用于描述系统在不同状态之间的转换逻辑。其核心思想是将复杂的行为拆解为有限的状态&#xff0c;并通过事件触发状态间的转移。 2.状态机…

2024年第十五届蓝桥杯CC++大学A组--成绩统计

2024年第十五届蓝桥杯C&C大学A组--成绩统计 题目&#xff1a; 动态规划&#xff0c; 对于该题&#xff0c;考虑动态规划解法&#xff0c;先取前k个人的成绩计算其方差&#xff0c;并将成绩记录在数组中&#xff0c;记录当前均值&#xff0c;设小蓝已检查前i-1个人的成绩&…

Kotlin 学习-集合

/*** kotlin 集合* List:是一个有序列表&#xff0c;可通过索引&#xff08;下标&#xff09;访问元素。元素可以在list中出现多次、元素可重复* Set:是元素唯一的集合。一般来说 set中的元素顺序并不重要、无序集合* Map:&#xff08;字典&#xff09;是一组键值对。键是唯一的…