日常更新一些笔记

This commit is contained in:
2026-06-22 22:11:42 +08:00
parent 69d4197074
commit df678ecd83
17 changed files with 1428 additions and 9 deletions
+423
View File
@@ -0,0 +1,423 @@
# List
概念:
`List<T>` 是 C# 提供的==泛型集合类==
本质上可以理解为:==一个长度可变的泛型数组==
它可以:
1. 按下标访问元素
2. 自动扩容
3. 方便地增删查改
4. 保证集合中元素类型统一
命名空间:
```csharp
using System.Collections.Generic;
```
简单理解:
数组长度固定
`List<T>` 长度可以动态变化
而且比 `ArrayList` 更安全,因为它有明确类型
----
# 通常用法
1. 存储数量不固定的一组同类型数据
2. 需要频繁添加、删除、遍历元素
3. 作为项目里最常见的基础集合之一
4. 替代早期非泛型集合 `ArrayList`
实际开发中:
新项目里 `List<T>` 的使用频率非常高
很多时候它就是“默认列表容器”
----
# 语法
创建:
```csharp
List<int> list = new List<int>();
```
创建并赋初值:
```csharp
List<string> names = new List<string>() { "小明", "小红", "小刚" };
```
添加:
```csharp
list.Add(10);
```
访问:
```csharp
list[0]
```
数量:
```csharp
list.Count
```
----
# 基础案例
```csharp
using System;
using System.Collections.Generic;
List<int> list = new List<int>();
list.Add(10);
list.Add(20);
list.Add(30);
Console.WriteLine(list[0]);
Console.WriteLine(list[1]);
Console.WriteLine(list[2]);
Console.WriteLine(list.Count);
```
输出:
```text
10
20
30
3
```
理解:
1. `List<int>` 里只能放 `int`
2. 可以像数组一样通过下标访问
3. `Count` 表示当前实际元素个数
----
# 和 ArrayList 的区别
`ArrayList`
内部按 `object` 存储
可以混合存很多类型
取值时常常需要强制类型转换
值类型放进去会发生装箱拆箱
`List<T>`
内部是泛型集合
类型更明确
编译期就能检查类型错误
通常不会像 `ArrayList` 那样频繁发生装箱拆箱
对比表:
| 对比点 | `ArrayList` | `List<T>` |
|---|---|---|
| 类型 | 非泛型 | 泛型 |
| 存储 | `object` | 指定类型 `T` |
| 类型安全 | 较弱 | 更强 |
| 取值 | 常要强转 | 一般不用强转 |
| 性能 | 值类型可能有装箱拆箱 | 通常更好 |
| 推荐程度 | 主要用于学习旧集合 | 实际开发常用 |
----
# 增删查改
增加:
```csharp
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Insert(1, 99);
list.AddRange(new List<int> { 7, 8, 9 });
```
删除:
```csharp
list.Remove(2); // 删除第一个匹配到的元素
list.RemoveAt(0); // 删除指定下标元素
list.Clear(); // 清空整个列表
```
查找:
```csharp
bool hasValue = list.Contains(99);
int index1 = list.IndexOf(99);
int index2 = list.LastIndexOf(99);
```
修改:
```csharp
list[0] = 100;
```
----
# 遍历
使用 `for`
```csharp
List<string> names = new List<string>() { "A", "B", "C" };
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine(names[i]);
}
```
使用 `foreach`
```csharp
foreach (string item in names)
{
Console.WriteLine(item);
}
```
说明:
如果只是读取元素,`foreach` 写起来更方便
如果需要下标,通常用 `for`
----
# Count 和 Capacity
`Count`
当前实际有多少个元素
`Capacity`
内部数组当前能容纳多少个元素
```csharp
List<int> list = new List<int>();
Console.WriteLine(list.Count);
Console.WriteLine(list.Capacity);
list.Add(10);
list.Add(20);
Console.WriteLine(list.Count);
Console.WriteLine(list.Capacity);
```
理解:
`List<T>` 会自动扩容
所以 `Capacity` 往往大于等于 `Count`
----
# 常用成员
```csharp
List<int> list = new List<int>() { 3, 1, 2, 1 };
Console.WriteLine(list.Count);
Console.WriteLine(list.Contains(2));
Console.WriteLine(list.IndexOf(1));
Console.WriteLine(list.LastIndexOf(1));
list.Sort();
list.Reverse();
```
常用方法:
1. `Add(T item)`:添加一个元素
2. `AddRange(IEnumerable<T>)`:添加一组元素
3. `Insert(int index, T item)`:插入元素
4. `Remove(T item)`:删除第一个匹配项
5. `RemoveAt(int index)`:按下标删除
6. `Clear()`:清空
7. `Contains(T item)`:判断是否存在
8. `IndexOf(T item)`:正向查找下标
9. `LastIndexOf(T item)`:反向查找下标
10. `Sort()`:排序
11. `Reverse()`:反转
----
# 排序和反转
排序:
```csharp
List<int> list = new List<int>() { 3, 5, 1, 2 };
list.Sort();
```
结果:
```text
1 2 3 5
```
反转:
```csharp
list.Reverse();
```
结果:
```text
5 3 2 1
```
说明:
`Sort()` 默认按从小到大排序
`Reverse()` 是把当前顺序直接反过来
----
# 插入和删除时要注意下标
错误示例:
```csharp
List<int> list = new List<int>();
list.Add(10);
// list[1] = 20;
// list.RemoveAt(5);
```
原因:
下标越界会报错
更稳的写法:
```csharp
if (list.Count > 0)
{
Console.WriteLine(list[0]);
}
```
说明:
`List<T>` 虽然长度可变
但访问下标时仍然必须合法
----
# 泛型的好处
```csharp
List<int> numbers = new List<int>();
numbers.Add(10);
// numbers.Add("hello");
```
说明:
`List<int>` 只能存 `int`
`"hello"` 这种类型不匹配的值,编译阶段就会报错
优点:
1. 类型安全
2. 减少强制类型转换
3. 代码提示更清楚
4. 更适合实际开发
----
# 基础案例:怪物列表
```csharp
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
Monster monster1 = new Boss();
Monster monster2 = new Goblin();
Monster monster3 = new Boss();
Monster monster4 = new Goblin();
for (int i = 0; i < Monster.Monsters.Count; i++)
{
Monster.Monsters[i].Atk();
}
}
}
abstract class Monster
{
public static List<Monster> Monsters = new List<Monster>();
public Monster()
{
Monsters.Add(this);
}
public abstract void Atk();
}
class Boss : Monster
{
public override void Atk()
{
Console.WriteLine("Boss Atk");
}
}
class Goblin : Monster
{
public override void Atk()
{
Console.WriteLine("Goblin Atk");
}
}
```
输出:
```text
Boss Atk
Goblin Atk
Boss Atk
Goblin Atk
```
理解:
1. `List<Monster>` 用来统一保存所有怪物对象
2. 因为 `Boss``Goblin` 都继承 `Monster`
3. 所以它们都能放进 `List<Monster>`
4. 再通过遍历统一调用攻击方法
----
# 适合场景
1. 玩家背包中的物品列表
2. 敌人列表、角色列表、任务列表
3. 聊天消息列表
4. 成绩列表、订单列表、日志列表
一句话:
只要你需要“数量不固定的一组同类型数据”
通常都可以先考虑 `List<T>`
----
# 注意
1. `List<T>``System.Collections.Generic` 命名空间中
2. `List<T>` 是泛型集合,`T` 表示元素类型
3. `Count` 是实际元素个数,不是容量
4. `Capacity` 是当前容量,可能大于 `Count`
5. `Add` 是追加到末尾
6. `Insert` 是插入到指定位置
7. `Remove` 删除的是第一个匹配项
8. `RemoveAt` 删除的是指定下标元素
9. `List<T>` 很常用,但按下标中间插入/删除很多次时会有移动开销
----
# 易错点
1. `List<T>` 是类,不是数组,但用法上和数组有点像
2. `Count` 不是 `Length`
3. `Capacity` 不是当前元素数量
4. `foreach` 遍历时一般不要直接改集合内容
5. 下标访问、`Insert``RemoveAt` 都要注意越界
错误示例:
```csharp
List<int> list = new List<int>() { 10, 20, 30 };
// Console.WriteLine(list[3]);
```
原因:
下标从 `0` 开始
上面这个列表只有 `0``1``2` 三个有效下标
----
# 一句话记忆
==List<T> 是长度可变、类型安全、最常用的泛型列表集合。==
----
# 面试/复习时怎么说
可以这样答:
`List<T>` 是 C# 中非常常用的泛型集合,本质上可以理解成长度可变的数组。
它支持按下标访问,也支持方便的增删查改,比如 `Add``Insert``Remove``RemoveAt`
相比 `ArrayList``List<T>` 类型更安全,通常不需要强制类型转换,所以在实际开发中更常用。”
----
引用:
1. Microsoft Learn: [List<T> Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-9.0)
2. Microsoft Learn: [System.Collections.Generic Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic?view=net-9.0)
#List
#泛型集合
#集合
#进阶