一、前置基础(MVC学习前提)_核心特性_【C# 泛型入门】为什么说 List<T>是程序员的 “万能收纳盒“?避坑指南在此

目录

    • 一、List<T>是什么?先看一个生活类比
    • 二、List<T>基础用法:从创建到常用操作
      • [1. 最简单的例子:创建一个 "整数盒子"](#1. 最简单的例子:创建一个 "整数盒子")
      • [2. 进阶操作:增删改查全掌握](#2. 进阶操作:增删改查全掌握)
    • [三、新手必踩的 5 个坑,附解决方案](#三、新手必踩的 5 个坑,附解决方案)
      • [坑 1:未初始化就用,直接报空引用](#坑 1:未初始化就用,直接报空引用)
      • [坑 2:往 List 里塞 null,取用时翻车](#坑 2:往 List 里塞 null,取用时翻车)
      • [坑 3:索引越界,以为 "Count 等于最大索引"](#坑 3:索引越界,以为 "Count 等于最大索引")
      • [坑 4:遍历同时修改集合,直接崩溃](#坑 4:遍历同时修改集合,直接崩溃)
      • [坑 5:用 Contains 判断自定义对象,永远返回 false](#坑 5:用 Contains 判断自定义对象,永远返回 false)
    • [四、为什么 MVC 里到处都是 List<T>?](#四、为什么 MVC 里到处都是 List<T>?)
    • 互动时间

大家好,我是William_cl。今天咱们聊一个 C# 里几乎天天用,但新手容易踩坑的东西 ------ 泛型集合List。如果你写代码时还在纠结 "数组长度不够用"、"存数据总担心类型错",那这篇文章一定要看完。

一、List是什么?先看一个生活类比

你家里肯定有这样的收纳盒:

  • 专门放袜子的抽屉(只装袜子,不乱)
  • 专门放充电器的盒子(线再多,不会和袜子混一起)
    List就像这种 "带标签的收纳盒",就是标签,比如List是 "只装整数的盒子",List是 "只装字符串的盒子"。
    对比一下 "旧时代的盒子":
  • 普通数组int[]:容量固定,装满了想多放一个都不行(比如定义int[3],最多放 3 个元素)
  • 非泛型集合ArrayList:啥都能装(int、string、对象混着来),取出来时经常认错类型
    而List的优势就俩字:灵活(容量自动扩)+安全(只装指定类型)。

二、List基础用法:从创建到常用操作

1. 最简单的例子:创建一个 "整数盒子"

csharp 复制代码
using System;
using System.Collections.Generic; // 注意:必须引用这个命名空间

class Program
{
    static void Main(string[] args)
    {
        // 创建一个只能装int的List(标签是int)
        List<int> numbers = new List<int>();
        
        // 往里面加元素(Add方法)
        numbers.Add(10);
        numbers.Add(20);
        numbers.Add(30);
        
        // 直接打印数量(Count属性)
        Console.WriteLine($"当前有{numbers.Count}个元素"); // 输出:3
        
        // 访问单个元素(和数组一样用索引)
        Console.WriteLine("第二个元素是:" + numbers[1]); // 输出:20
        
        // 遍历所有元素(foreach最方便)
        Console.WriteLine("所有元素:");
        foreach (int num in numbers)
        {
            Console.WriteLine(num);
        }
    }
}

2. 进阶操作:增删改查全掌握

csharp 复制代码
// 1. 初始化时直接填数据
List<string> fruits = new List<string> { "苹果", "香蕉", "橙子" };

// 2. 插入元素(在指定位置加)
fruits.Insert(1, "草莓"); // 在索引1的位置插入,结果:苹果、草莓、香蕉、橙子

// 3. 删除元素(两种方式)
fruits.Remove("香蕉"); // 直接删值:苹果、草莓、橙子
fruits.RemoveAt(0); // 删索引0的元素:草莓、橙子

// 4. 查找元素
bool hasOrange = fruits.Contains("橙子"); // 有没有橙子?true
int index = fruits.IndexOf("草莓"); // 草莓在哪个位置?0

// 5. 清空所有元素
fruits.Clear();
Console.WriteLine(fruits.Count); // 输出:0

三、新手必踩的 5 个坑,附解决方案

坑 1:未初始化就用,直接报空引用

csharp 复制代码
List<int> nums;
nums.Add(1); // 报错:未将对象引用设置到对象的实例
原因:只声明了变量,没new List<int>()创建实例,就像买了个空盒子但没拆开用。解决:声明时直接初始化:List<int> nums = new List<int>();

坑 2:往 List 里塞 null,取用时翻车

csharp 复制代码
List<string> names = new List<string>();
names.Add(null); // 允许添加null
string first = names[0];
int length = first.Length; // 报错:未将对象引用设置到对象的实例

原因: List允许添加 null(除非 T 是值类型如 int),但后续操作 null 会报错。
解决: 添加前判断,或遍历前检查:

csharp 复制代码
// 添加时过滤null
if (name != null) names.Add(name);

// 遍历时有备无患
foreach (var n in names)
{
    if (n != null)
    {
        Console.WriteLine(n.Length);
    }
}

坑 3:索引越界,以为 "Count 等于最大索引"

csharp 复制代码
List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(list[3]); // 报错:索引超出范围

原因: Count是元素总数,最大索引是Count-1(3 个元素,索引 0、1、2)。
解决: 访问前先判断:

csharp 复制代码
if (index >= 0 && index < list.Count)
{
    // 安全访问
}

坑 4:遍历同时修改集合,直接崩溃

csharp 复制代码
List<int> numbers = new List<int> { 1, 2, 3 };
foreach (int num in numbers)
{
    if (num == 2)
    {
        numbers.Remove(num); // 报错:集合已修改,可能无法执行枚举操作
    }
}

原因: foreach 遍历是 "只读模式",中途增删元素会破坏遍历状态。
解决: 用 for 循环倒序遍历(避免索引偏移):

csharp 复制代码
for (int i = numbers.Count - 1; i >= 0; i--)
{
    if (numbers[i] == 2)
    {
        numbers.RemoveAt(i); // 安全删除
    }
}

坑 5:用 Contains 判断自定义对象,永远返回 false

csharp 复制代码
public class Person
{
    public string Name { get; set; }
    public Person(string name) { Name = name; }
}

// 测试代码
List<Person> people = new List<Person>();
people.Add(new Person("张三"));

// 想判断是否有"张三"
bool hasZhang = people.Contains(new Person("张三")); // 结果:false

原因: Contains默认比较 "对象地址"(引用类型),两个new Person("张三")是不同对象,地址不同。
解决: 让 Person 类实现IEquatable接口,自定义比较规则:

csharp 复制代码
public class Person : IEquatable<Person>
{
    public string Name { get; set; }
    public Person(string name) { Name = name; }
    
    // 自定义比较逻辑:只要Name相同就认为相等
    public bool Equals(Person other)
    {
        return other != null && Name == other.Name;
    }
}
// 此时再调用Contains就会返回true了

四、为什么 MVC 里到处都是 List?

在 MVC 开发中,List简直是 "刚需":

  • 控制器(Controller)从数据库查数据,用List存商品列表
  • 视图(View)接收List,用 foreach 遍历显示用户表格
  • 模型(Model)里的集合属性,几乎都是List(如public List Orders { get; set; })
    它就像 MVC 各层之间的 "数据传送带",安全又高效。

互动时间

你在使用List时踩过哪些奇葩的坑?有没有什么提高效率的小技巧(比如Capacity预分配容量)?欢迎在评论区分享,点赞最高的评论送我整理的《C# 集合操作手册》一份~

下一期咱们聊 LINQ,看看怎么用一行代码搞定 List 的复杂查询,不见不散!

相关推荐
菜鸟‍4 小时前
【论文学习】大语言模型(LLM)论文
论文阅读·人工智能·学习
William_cl4 小时前
【C# OOP 入门到精通】从基础概念到 MVC 实战(含 SOLID 原则与完整代码)
开发语言·c#·mvc
我先去打把游戏先4 小时前
ESP32学习笔记(基于IDF):IOT应用——WIFI连接
笔记·单片机·嵌入式硬件·mcu·物联网·学习·esp32
Brookty4 小时前
【算法】前缀和
java·学习·算法·前缀和·动态规划
。TAT。5 小时前
C++ - List
数据结构·c++·学习
张永清-老清6 小时前
每周读书与学习->JMeter主要元件详细介绍(一)配置元件
学习·jmeter·性能调优·jmeter性能测试·性能分析·干货分享
鼾声鼾语7 小时前
grootN1 grootN1.5 gr00t安装方法以及使用(学习)
学习·angular.js·simulink·isaacsim·isaaclab
MYX_3097 小时前
第七章 完整的模型训练
pytorch·python·深度学习·学习
Larry_Yanan8 小时前
QML学习笔记(四十三)QML与C++交互:上下文属性暴露
c++·笔记·qt·学习·ui·交互
励志成为美貌才华为一体的女子8 小时前
pdf解析工具---Miner-u 本地部署记录
学习·pdf