首页/新闻资讯/正文详情

一排“储物柜“的智慧:从 C# 数组到 List<T>,看懂数据集合的进化之路

发布时间:2026/9/24 17:37:41 来源:云帆数科 栏目:资讯中心
一排“储物柜“的智慧:从 C# 数组到 List<T>,看懂数据集合的进化之路
一句话概括数组是编译器为你划出的一排连号储物柜——快、稳、但一旦建成就不能扩建ListT则是会自动扩建的智能储物间。搞懂它们的取舍你才算真正会存数据。一、先从一个尴尬场景说起你要统计班里 5 名学生的成绩。新手最直观的写法是intscore188;intscore292;intscore375;intscore460;intscore595;求平均分(score1 score2 score3 score4 score5) / 5。如果班里有 50 人呢500 人呢难道要写 500 个变量这就是数组存在的意义用一个名字管理一整排同类型的数据。二、数组Array连号储物柜2.1 它是什么数组是长度固定、元素类型相同、在内存中连续存放的数据结构。想象一排编号从 0 开始的储物柜索引: [0] [1] [2] [3] [4] 值: 88 92 75 60 95每个柜子只能放同一种类型的东西柜子总数创建时就定死了通过**编号索引**直接开柜速度极快O(1)2.2 四种创建方式// ① 指定长度元素为默认值int 默认 0int[]anewint[5];// ② 声明 初始化int[]bnewint[]{88,92,75,60,95};// ③ 简写最常用int[]scores{88,92,75,60,95};// ④ C# 12 集合表达式int[]c[88,92,75,60,95];2.2 读取、修改与遍历int[]scores{88,92,75,60,95};Console.WriteLine(scores[0]);// 88索引从 0 开始scores[3]65;// 修改Console.WriteLine(scores.Length);// 5// 遍历只读用 foreach需要索引用 forforeach(intsinscores)Console.Write(s );for(inti0;iscores.Length;i)Console.WriteLine($第{i1}位同学{scores[i]}分);2.3 现代 C# 的两个糖^与..int[]scores{88,92,75,60,95};Console.WriteLine(scores[^1]);// 95倒数第 1 个Console.WriteLine(scores[^2]);// 60倒数第 2 个int[]middlescores[1..4];// 取索引 1 到 3含头不含尾Console.WriteLine(string.Join(,,middle));// 92,75,60提示对数组使用..切片会复制出一个新数组而不是原数组的视图。2.4Array类自带的实用工具int[]scores{88,92,75,60,95};Array.Sort(scores);// 升序60,75,88,92,95Array.Reverse(scores);// 反转95,92,88,75,60intidxArray.IndexOf(scores,88);// 查找返回索引找不到返回 -1boolhasArray.Exists(scores,ss60);// 是否存在不及格int[]copy(int[])scores.Clone();// 浅拷贝Array.Clear(scores,0,scores.Length);// 全部清零2.5 多维数组与交错数组// 矩形数组3 行 4 列每行一样长int[,]gridnewint[3,4];grid[1,2]99;Console.WriteLine(grid.GetLength(0));// 3行数Console.WriteLine(grid.GetLength(1));// 4列数// 交错数组数组的数组每行长度可以不同int[][]jaggednewint[3][];jagged[0]newint[]{1};jagged[1]newint[]{2,3};jagged[2]newint[]{4,5,6};Console.WriteLine(jagged[2][1]);// 5类型语法特点矩形数组int[,]每行等长像 Excel 表格交错数组int[][]每行可不等长更灵活通常性能更好三、实战演示班级成绩分析器我们用纯数组完成一个小项目输入一批成绩输出最高分、最低分、平均分、排名和分数段分布。usingSystem;classProgram{staticvoidMain(){string[]names{小明,小红,小刚,小美,小强,小丽};int[]scores{88,92,75,59,95,67};// ---------- 1. 基础统计 ----------intmaxscores[0],minscores[0],sum0;intmaxIdx0,minIdx0;for(inti0;iscores.Length;i){sumscores[i];if(scores[i]max){maxscores[i];maxIdxi;}if(scores[i]min){minscores[i];minIdxi;}}doubleavg(double)sum/scores.Length;Console.WriteLine( 成绩概览 );Console.WriteLine($最高分{names[maxIdx]}{max}分);Console.WriteLine($最低分{names[minIdx]}{min}分);Console.WriteLine($平均分{avg:F1}分);// ---------- 2. 分数段统计用数组做计数器 ----------// 索引含义0不及格 160-79 280-89 390以上int[]bandsnewint[4];foreach(intsinscores){if(s60)bands[0];elseif(s80)bands[1];elseif(s90)bands[2];elsebands[3];}string[]bandNames{不及格,60-79 ,80-89 ,90以上};Console.WriteLine(\n 分数段分布 );for(inti0;ibands.Length;i)Console.WriteLine(${bandNames[i]}|{newstring(■,bands[i])}{bands[i]}人);// ---------- 3. 排名成绩与姓名同步排序 ----------// Array.Sort(keys, items)按 keys 排序同时移动 itemsint[]sortedScores(int[])scores.Clone();string[]sortedNames(string[])names.Clone();Array.Sort(sortedScores,sortedNames);// 升序Array.Reverse(sortedScores);Array.Reverse(sortedNames);// 变成降序Console.WriteLine(\n 排行榜 );for(inti0;isortedScores.Length;i)Console.WriteLine($第{i1}名{sortedNames[i]}{sortedScores[i]}分);}}运行结果 成绩概览 最高分小强 95 分 最低分小美 59 分 平均分79.3 分 分数段分布 不及格 | ■ 1 人 60-79 | ■■ 2 人 80-89 | ■ 1 人 90以上 | ■■ 2 人 排行榜 第 1 名小强 95 分 第 2 名小红 92 分 第 3 名小明 88 分 第 4 名小刚 75 分 第 5 名小丽 67 分 第 6 名小美 59 分这个例子里有个很典型的技巧用数组下标本身来表达含义bands的索引对应分数段这是数组最优雅的用法之一。四、数组的天花板为什么我们需要 List回头看上面的代码你有没有嗅到几个不对劲的地方名字和成绩是两个平行数组靠下标相同来对应。一旦排序时漏掉同步数据就错位了。长度写死。如果新转来一位同学你得新建更大的数组、把旧数据一个个搬过去。想删除某位同学数组没有Remove只能手动挪位置。这些痛点一个是数据建模问题应该用类把姓名和成绩绑在一起一个是容量问题应该用能自动伸缩的集合。答案就是List类。五、ListT会自动扩建的智能储物间5.1 它是什么ListT是System.Collections.Generic命名空间下的泛型动态列表。T是你要存放的类型可以是int、string更常见的是你自己定义的类底层依然是数组但由框架帮你管理扩容支持增、删、查、排序等一整套方法5.2 它是怎么自动扩建的varlistnewListint();Console.WriteLine(list.Capacity);// 0list.Add(1);Console.WriteLine(list.Capacity);// 4for(inti0;i4;i)list.Add(i);Console.WriteLine(list.Capacity);// 8装不下时容量翻倍原理当元素个数超出容量ListT会新建一个容量翻倍的内部数组把旧数据复制过去。性能小技巧如果你事先大概知道会放多少元素直接指定容量可以避免反复扩容var list new Listint(10000);5.3 重头戏List类真实项目中我们几乎不会存一堆孤立的int而是存对象。先把姓名与成绩封装成一个类publicclassStudent{publicintId{get;}publicstringName{get;}publicintScore{get;set;}publicStudent(intid,stringname,intscore){Idid;Namename;Scorescore;}publicoverridestringToString()$[{Id}]{Name}{Score}分;}然后一个ListStudent就替代了之前的两个平行数组usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;classProgram{staticvoidMain(){// 1. 创建并初始化varstudentsnewListStudent{newStudent(1,小明,88),newStudent(2,小红,92),newStudent(3,小刚,75),newStudent(4,小美,59),};// 2. 新同学转入直接 Add无需操心容量students.Add(newStudent(5,小强,95));// 3. 查找Student?targetstudents.Find(ss.Name小红);Console.WriteLine($找到{target});// 4. 修改List 里存的是对象引用改对象就是改列表里的数据if(target!null)target.Score5;// 5. 删除批量删除不及格的同学intremovedstudents.RemoveAll(ss.Score60);Console.WriteLine($移除了{removed}位不及格同学);// 6. 排序按成绩降序students.Sort((a,b)b.Score.CompareTo(a.Score));Console.WriteLine(\n 排行榜 );for(inti0;istudents.Count;i)// 注意List 用 Count数组用 LengthConsole.WriteLine($第{i1}名{students[i]});// 7. 配合 LINQ统计变得极其简单Console.WriteLine($\n平均分{students.Average(ss.Score):F1});Console.WriteLine($最高分{students.Max(ss.Score)});Console.WriteLine(90 分以上string.Join(、,students.Where(ss.Score90).Select(ss.Name)));}}运行结果找到[2] 小红92 分 移除了 1 位不及格同学 排行榜 第 1 名 [2] 小红97 分 第 2 名 [5] 小强95 分 第 3 名 [1] 小明88 分 第 4 名 [3] 小刚75 分 平均分88.8 最高分97 90 分以上小红、小强对比一下之前的数组版本没有平行数组没有手动搬运没有下标错位排序、查找、删除都是一行代码的事。5.4ListT常用方法速查方法 / 属性作用示例Add(item)末尾添加list.Add(stu)AddRange(items)批量添加list.AddRange(others)Insert(i, item)在指定位置插入list.Insert(0, stu)Remove(item)删除第一个匹配项list.Remove(stu)RemoveAt(i)按索引删除list.RemoveAt(2)RemoveAll(pred)按条件批量删除list.RemoveAll(s s.Score 60)Find/FindAll查找单个 / 全部list.FindAll(s s.Score 90)Contains(item)是否包含list.Contains(stu)Sort(comparison)原地排序list.Sort((a, b) ...)Count当前元素个数list.CountClear()清空list.Clear()ToArray()转回数组var arr list.ToArray();六、数组 vsListT到底该选谁对比维度数组T[]ListT长度固定创建后不可变动态自动扩容长度属性LengthCount增删元素不支持需手动搬运内置Add/Remove等多维支持原生支持[,]需嵌套ListListT性能极致无额外开销略有开销扩容、边界封装典型场景数据量固定、追求性能、底层 API数据量不确定、需要频繁增删选择口诀数量固定不变如一周 7 天、棋盘 8×8、RGB 三通道→数组数量会变、需要增删查改 →ListT拿不准先用ListT性能瓶颈出现时再优化七、高手都踩过的 5 个坑坑 1IndexOutOfRangeException越界int[]arrnewint[5];arr[5]1;// ❌ 有效索引是 0~4遍历时用i arr.Length而不是i arr.Length。ListT越界则抛出ArgumentOutOfRangeException。坑 2数组赋值是共享不是复制int[]a{1,2,3};int[]ba;// b 和 a 指向同一块内存b[0]99;Console.WriteLine(a[0]);// 99 int[]c(int[])a.Clone();// ✅ 真正复制坑 3foreach遍历时修改List会直接抛异常foreach(varsinstudents){if(s.Score60)students.Remove(s);// ❌ InvalidOperationException集合已修改}// ✅ 正确做法students.RemoveAll(ss.Score60);坑 4List类的拷贝只是浅拷贝varcopynewListStudent(students);// 新列表但里面装的仍是同一批对象copy[0].Score0;// students[0] 的分数也变成 0新列表只复制了引用对象本身是共享的。需要独立数据必须逐个克隆对象。坑 5忘记判断Find的返回值可能为nullvarstustudents.Find(ss.Name不存在的人);Console.WriteLine(stu.Score);// ❌ NullReferenceExceptionif(stu!null){/* ✅ 先判空 */}八、写在最后数组与ListT的关系就像自行车与汽车数组简单、轻快、没有多余零件适合固定路线ListT功能齐全、自动挡适合复杂多变的日常通勤。而用类封装数据再用List类管理对象几乎是每一个 C# 业务系统的基本骨架——订单列表、用户列表、商品列表无一例外。掌握这套组合拳你就跨过了会写代码到会建模的第一道门槛。 课后练习用二维数组int[,]实现一个 3×3 井字棋的棋盘打印。给Student增加ClassName属性用ListStudent配合 LINQ 的GroupBy统计每个班的平均分。写一个方法实现深拷贝一个ListStudent并验证修改副本不会影响原列表。觉得有收获欢迎收藏并转发给那个还在用 5 个变量存 5 个成绩的朋友

相关推荐

高炉智能布料技术与炉料分布优化~系列文章23:智能布料十大避坑指南:前人踩过的坑,你不必再踩
高炉智能布料技术与炉料分布优化~系列文章23:智能布料十大避坑指南:前人踩过的坑,你不必再踩

第 23 期 | 智能布料十大避坑指南:前人踩过的坑,你不必再踩智能布料是高炉智能化中最成熟、效益最明确的方向之一,但也是"坑"最多的方向之一。从工艺机理到数据基础,从模型构建到工程落地,每个环节都埋伏着让… · 2026/9/24 17:37:41

美业四端管理系统|四端数据联动踩坑复盘・上篇(预约、排班、疗程储值、会员资产同步)
美业四端管理系统|四端数据联动踩坑复盘・上篇(预约、排班、疗程储值、会员资产同步)

📌项目简介本专栏完整记录一套面向中小型美容、美甲、皮肤管理单门店四端一体化管理系统的全栈开发过程,基于微信云开发实现,无需自建服务器,覆盖顾客、技师、管理员小程序以及 Vue3 PC 管理后台完整业务闭环。前面第四篇复盘的全… · 2026/9/24 17:37:41

学习嵌入式Day7:C语言之排序算法和字符型数组
学习嵌入式Day7:C语言之排序算法和字符型数组

上一篇写到一维数组&#xff0c;今天接着展开。一、冒泡排序算法相邻两个元素比较&#xff0c;小的放在前&#xff0c;大的放在后&#xff0c;最终实现升序排序。#include <stdio.h>int main(void) {int a[10] {};int len sizeof(a)/sizeof(a[0]);int i 0;printf(&quo… · 2026/9/24 17:37:29

手写RTSPClient:从协议原理到工业级拉流实战
手写RTSPClient:从协议原理到工业级拉流实战

简介&#xff1a;这是一份面向嵌入式开发与流媒体协议学习者的 RTSP 客户端轻量级实现源码包&#xff0c;适用于 C/C 开发者快速理解并实践 RTSP 协议交互流程&#xff0c;解决音视频流控制、会话管理及底层传输调试等实际问题。资源共 7 个文件&#xff0c;含 3 个头文件&… · 2026/9/24 18:12:42

遥感影像滑坡场景分类实战:基于ResNet迁移学习的完整指南
遥感影像滑坡场景分类实战:基于ResNet迁移学习的完整指南

简介&#xff1a;基于Python的遥感影像滑坡场景分类任务代码与配套项目文档&#xff0c;面向毕业设计、课程设计及项目开发场景&#xff0c;适合具备Python与机器学习基础、希望快速上手图像分类完整流程的开发者。压缩包共21个文件&#xff0c;大小仅1.86MB&#xff0c;包含4个… · 2026/9/24 18:12:41

商品评论情感分析实战:从数据清洗到模型评估全流程
商品评论情感分析实战:从数据清洗到模型评估全流程

简介&#xff1a;一套完整的基于机器学习的商品评论情感分析毕业设计项目资料&#xff0c;覆盖数据采集、预处理、模型训练到界面展示全流程&#xff0c;适合计算机、人工智能、电子信息等专业学生作为毕设或课程设计参考。项目主体使用Python实现&#xff0c;包含SVM、LSTM、W… · 2026/9/24 18:12:41

YOLOV8路面桥梁墙体裂缝识别Python实战:从训练到损失曲线分析
YOLOV8路面桥梁墙体裂缝识别Python实战:从训练到损失曲线分析

简介&#xff1a;这是一份基于YOLOv8的路面、桥梁与墙体裂缝识别项目&#xff0c;面向深度学习初学者、计算机视觉方向学生及需要完成课程设计或毕业设计的开发者&#xff0c;提供可直接运行的Python源码与配套文档。项目源码经过本地编译验证&#xff0c;评审分达到95分以上&a… · 2026/9/24 18:12:41

OPNET OSPF仿真实验包解析:三个场景对比与结果分析
OPNET OSPF仿真实验包解析:三个场景对比与结果分析

简介&#xff1a;这是一份基于Riverbed OpNet平台的OSPF路由协议仿真工程包&#xff0c;适合网络工程学习者、运维人员以及需要开展路由协议仿真研究的读者使用。包内核心文件krishospf.project可直接在OpNet中打开&#xff0c;用于搭建OSPF区域网络模型&#xff0c;配置路由器… · 2026/9/24 18:12:41

当你的论文终于定稿,真正的大考才刚刚开始——聊聊aigcbiye的AI PPT功能一个被忽视的真相
当你的论文终于定稿,真正的大考才刚刚开始——聊聊aigcbiye的AI PPT功能一个被忽视的真相

aigcbiye官网 微信公众号搜一搜 aigcbiye 我带了这么多年论文写作&#xff0c;发现一个特别有意思的现象&#xff1a;很多人把论文正文写完&#xff0c;长舒一口气&#xff0c;以为最难的关卡已经过了。然后他们打开PPT&#xff0c;新建一个空白文档&#xff0c;盯着那个闪烁的… · 2026/9/24 18:12:35

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介&#xff1a;这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源&#xff0c;围绕YOLOv8实现渔船作业监控系统&#xff0c;可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件&#xff0c;约24.21MB&#xff0c;以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介&#xff1a;面向时间序列数据建模的一维卷积神经网络完整实现&#xff0c;适合深度学习入门者及需要快速验证时序模型的研究者&#xff0c;能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小&#xff0c;只有3KB&#xff0c;内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L&#xff0c;而是舌尖上的L最近在几个方言群和语音教学社群里&#xff0c;反复看到有人发一句&#xff1a;“也说字母L&#xff1a;柔软的长舌”。初看以为是英语发音课笔记&#xff0c;点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码