home commit with new plugins
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
# ArrayList
|
||||
概念:
|
||||
`ArrayList` 是 C# 提供的一个==非泛型集合类==
|
||||
本质上可以理解成:==一个长度可变的 `object` 数组==
|
||||
|
||||
它可以:
|
||||
1. 像数组一样按下标访问
|
||||
2. 自动扩容
|
||||
3. 增删查改元素
|
||||
4. 存储任意类型的对象
|
||||
|
||||
命名空间:
|
||||
```csharp
|
||||
using System.Collections;
|
||||
```
|
||||
|
||||
注意:
|
||||
是 `System.Collections`
|
||||
不是 `System.Collection`
|
||||
|
||||
----
|
||||
# 通常用法
|
||||
1. 学习 C# 早期非泛型集合
|
||||
2. 理解 `object`、装箱和拆箱
|
||||
3. 存储数量不固定的数据
|
||||
4. 对数组进行更方便的增删操作
|
||||
|
||||
实际开发中:
|
||||
新代码更推荐使用 `List<T>`
|
||||
`ArrayList` 主要作为进阶阶段理解集合历史和装箱拆箱的材料
|
||||
|
||||
----
|
||||
# 语法
|
||||
创建:
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
```
|
||||
|
||||
添加:
|
||||
```csharp
|
||||
list.Add(数据);
|
||||
```
|
||||
|
||||
访问:
|
||||
```csharp
|
||||
list[下标]
|
||||
```
|
||||
|
||||
长度:
|
||||
```csharp
|
||||
list.Count
|
||||
```
|
||||
|
||||
----
|
||||
# 基础案例
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
list.Add("小明");
|
||||
list.Add(18);
|
||||
list.Add(true);
|
||||
|
||||
Console.WriteLine(list[0]);
|
||||
Console.WriteLine(list[1]);
|
||||
Console.WriteLine(list[2]);
|
||||
Console.WriteLine(list.Count);
|
||||
```
|
||||
|
||||
理解:
|
||||
1. `ArrayList` 内部存的是 `object`
|
||||
2. 所以字符串、整数、布尔值都可以放进去
|
||||
3. `Count` 表示当前实际存了多少个元素
|
||||
|
||||
----
|
||||
# 增删查改
|
||||
增加:
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
list.Add("A");
|
||||
list.Add("B");
|
||||
list.Insert(1, "C");
|
||||
```
|
||||
|
||||
结果:
|
||||
```text
|
||||
A C B
|
||||
```
|
||||
|
||||
删除:
|
||||
```csharp
|
||||
list.Remove("A"); // 删除第一个匹配的元素
|
||||
list.RemoveAt(0); // 删除指定下标的元素
|
||||
list.Clear(); // 清空所有元素
|
||||
```
|
||||
|
||||
查找:
|
||||
```csharp
|
||||
bool hasB = list.Contains("B");
|
||||
int index = list.IndexOf("B");
|
||||
```
|
||||
|
||||
修改:
|
||||
```csharp
|
||||
list[0] = "新的值";
|
||||
```
|
||||
|
||||
----
|
||||
# 遍历
|
||||
使用 `for`:
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add("A");
|
||||
list.Add("B");
|
||||
list.Add("C");
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
Console.WriteLine(list[i]);
|
||||
}
|
||||
```
|
||||
|
||||
使用 `foreach`:
|
||||
```csharp
|
||||
foreach (object item in list)
|
||||
{
|
||||
Console.WriteLine(item);
|
||||
}
|
||||
```
|
||||
|
||||
因为 `ArrayList` 中的元素都是按 `object` 看待,所以 `foreach` 变量常写成 `object`。
|
||||
|
||||
----
|
||||
# 取值时要类型转换
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add(100);
|
||||
|
||||
int num = (int)list[0];
|
||||
Console.WriteLine(num);
|
||||
```
|
||||
|
||||
原因:
|
||||
`list[0]` 的返回类型是 `object`
|
||||
如果要当成 `int` 使用,就需要拆箱 / 强制类型转换
|
||||
|
||||
错误示意:
|
||||
```csharp
|
||||
int num = list[0];
|
||||
```
|
||||
|
||||
这样会报错,因为不能把 `object` 直接赋值给 `int`。
|
||||
|
||||
----
|
||||
# 装箱和拆箱问题
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
int hp = 100;
|
||||
list.Add(hp); // int 放进 object,发生装箱
|
||||
|
||||
int value = (int)list[0]; // object 取回 int,发生拆箱
|
||||
```
|
||||
|
||||
理解:
|
||||
1. 值类型放进 `ArrayList` 时,会发生装箱
|
||||
2. 从 `ArrayList` 取出值类型时,需要拆箱
|
||||
3. 装箱和拆箱都有额外开销
|
||||
4. 类型转错还会运行时报错
|
||||
|
||||
这个点可以和[[万物之父和装箱与拆箱|装箱与拆箱]]一起理解。
|
||||
|
||||
----
|
||||
# Capacity 和 Count
|
||||
`Count`:
|
||||
当前实际有多少个元素
|
||||
|
||||
`Capacity`:
|
||||
内部数组当前能容纳多少个元素
|
||||
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
Console.WriteLine(list.Count);
|
||||
Console.WriteLine(list.Capacity);
|
||||
|
||||
list.Add("A");
|
||||
list.Add("B");
|
||||
|
||||
Console.WriteLine(list.Count);
|
||||
Console.WriteLine(list.Capacity);
|
||||
```
|
||||
|
||||
理解:
|
||||
`ArrayList` 内部会自动扩容
|
||||
`Count` 是实际数量
|
||||
`Capacity` 是容量,不一定等于数量
|
||||
|
||||
----
|
||||
# 排序和反转
|
||||
排序:
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add(3);
|
||||
list.Add(1);
|
||||
list.Add(2);
|
||||
|
||||
list.Sort();
|
||||
```
|
||||
|
||||
反转:
|
||||
```csharp
|
||||
list.Reverse();
|
||||
```
|
||||
|
||||
注意:
|
||||
如果里面混放了不能互相比较的类型,`Sort()` 可能会出错
|
||||
|
||||
例如:
|
||||
```csharp
|
||||
list.Add(10);
|
||||
list.Add("A");
|
||||
list.Sort(); // 可能出错
|
||||
```
|
||||
|
||||
所以虽然 `ArrayList` 可以存任意类型,但最好不要随便混放。
|
||||
|
||||
----
|
||||
# 和数组的区别
|
||||
| 对比点 | 数组 | ArrayList |
|
||||
| ---- | --------- | -------------- |
|
||||
| 长度 | 创建后固定 | 可以动态增删 |
|
||||
| 类型 | 通常固定一种类型 | 内部按 `object` 存 |
|
||||
| 访问 | 可以用下标 | 可以用下标 |
|
||||
| 性能 | 类型明确,性能较好 | 可能有装箱拆箱 |
|
||||
| 常用程度 | 基础常用 | 现在新项目较少用 |
|
||||
|
||||
----
|
||||
# 常见错误
|
||||
错误1:忘记引用命名空间
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
```
|
||||
|
||||
解决:
|
||||
```csharp
|
||||
using System.Collections;
|
||||
```
|
||||
|
||||
----
|
||||
错误2:取值时忘记强转
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add(10);
|
||||
|
||||
int num = list[0];
|
||||
```
|
||||
|
||||
应该写:
|
||||
```csharp
|
||||
int num = (int)list[0];
|
||||
```
|
||||
|
||||
----
|
||||
错误3:混放类型后强转错误
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add("100");
|
||||
|
||||
int num = (int)list[0];
|
||||
```
|
||||
|
||||
`list[0]` 实际是字符串,不是整数,会出错。
|
||||
|
||||
----
|
||||
# 注意
|
||||
1. `ArrayList` 在 `System.Collections` 命名空间中
|
||||
2. `ArrayList` 是非泛型集合,内部按 `object` 存储
|
||||
3. 它可以动态增删元素
|
||||
4. 取出元素时通常需要强制类型转换
|
||||
5. 值类型放入 `ArrayList` 会发生装箱
|
||||
6. 不建议随意混放不同类型,容易产生转换错误
|
||||
7. 新项目通常优先使用 `List<T>`,类型更安全
|
||||
|
||||
----
|
||||
# 一句话记忆
|
||||
==ArrayList 是会自动扩容的 object 数组,方便但不够类型安全。==
|
||||
|
||||
----
|
||||
# 面试/复习时怎么说
|
||||
可以这样答:
|
||||
|
||||
“ArrayList 是 `System.Collections` 命名空间下的非泛型集合,本质上可以理解为动态扩容的 `object` 数组。
|
||||
它可以存储任意类型,但取值时通常需要强制类型转换,值类型放进去还会发生装箱。
|
||||
所以它适合用来理解非泛型集合和装箱拆箱,新项目中一般更推荐使用泛型集合 `List<T>`。”
|
||||
|
||||
----
|
||||
引用:
|
||||
1. Microsoft Learn: [ArrayList Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=net-9.0)
|
||||
2. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)
|
||||
|
||||
#ArrayList
|
||||
#集合
|
||||
#进阶
|
||||
@@ -0,0 +1,315 @@
|
||||
# Hashtable
|
||||
概念:
|
||||
`Hashtable` 是 C# 提供的一个==非泛型键值对集合==
|
||||
它通过键 `key` 来查找值 `value`
|
||||
|
||||
简单理解:
|
||||
像一本字典
|
||||
用“词”查“解释”
|
||||
用 `key` 查 `value`
|
||||
|
||||
命名空间:
|
||||
```csharp
|
||||
using System.Collections;
|
||||
```
|
||||
|
||||
----
|
||||
# 通常用法
|
||||
1. 保存键值对数据
|
||||
2. 通过唯一键快速查找对应值
|
||||
3. 学习哈希表这种数据结构
|
||||
4. 理解 `Dictionary<TKey, TValue>` 之前的非泛型写法
|
||||
|
||||
实际开发中:
|
||||
新代码更推荐使用 `Dictionary<TKey, TValue>`
|
||||
`Hashtable` 主要用于学习非泛型键值对集合
|
||||
|
||||
----
|
||||
# 语法
|
||||
创建:
|
||||
```csharp
|
||||
Hashtable table = new Hashtable();
|
||||
```
|
||||
|
||||
添加:
|
||||
```csharp
|
||||
table.Add(键, 值);
|
||||
```
|
||||
|
||||
通过键取值:
|
||||
```csharp
|
||||
object value = table[键];
|
||||
```
|
||||
|
||||
修改:
|
||||
```csharp
|
||||
table[键] = 新值;
|
||||
```
|
||||
|
||||
数量:
|
||||
```csharp
|
||||
table.Count
|
||||
```
|
||||
|
||||
----
|
||||
# 基础案例
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
Hashtable table = new Hashtable();
|
||||
|
||||
table.Add("name", "小明");
|
||||
table.Add("age", 18);
|
||||
table.Add("isVip", true);
|
||||
|
||||
Console.WriteLine(table["name"]);
|
||||
Console.WriteLine(table["age"]);
|
||||
Console.WriteLine(table["isVip"]);
|
||||
```
|
||||
|
||||
理解:
|
||||
1. `"name"`、`"age"`、`"isVip"` 是键
|
||||
2. `"小明"`、`18`、`true` 是值
|
||||
3. 通过键可以找到对应的值
|
||||
|
||||
----
|
||||
# Add 和索引器
|
||||
使用 `Add` 添加:
|
||||
```csharp
|
||||
Hashtable table = new Hashtable();
|
||||
|
||||
table.Add("id", 1001);
|
||||
table.Add("name", "小明");
|
||||
```
|
||||
|
||||
使用索引器添加或修改:
|
||||
```csharp
|
||||
table["score"] = 90; // 如果 key 不存在,就是新增
|
||||
table["score"] = 100; // 如果 key 已存在,就是修改
|
||||
```
|
||||
|
||||
区别:
|
||||
1. `Add` 遇到重复键会报错
|
||||
2. `table[key] = value` 遇到重复键会覆盖旧值
|
||||
|
||||
----
|
||||
# 增删查改
|
||||
增加:
|
||||
```csharp
|
||||
table.Add("level", 10);
|
||||
```
|
||||
|
||||
删除:
|
||||
```csharp
|
||||
table.Remove("level");
|
||||
table.Clear();
|
||||
```
|
||||
|
||||
查找键:
|
||||
```csharp
|
||||
bool hasName = table.ContainsKey("name");
|
||||
```
|
||||
|
||||
查找值:
|
||||
```csharp
|
||||
bool hasValue = table.ContainsValue("小明");
|
||||
```
|
||||
|
||||
修改:
|
||||
```csharp
|
||||
table["name"] = "小红";
|
||||
```
|
||||
|
||||
取值:
|
||||
```csharp
|
||||
string name = (string)table["name"];
|
||||
```
|
||||
|
||||
----
|
||||
# 遍历
|
||||
遍历键值对:
|
||||
```csharp
|
||||
Hashtable table = new Hashtable();
|
||||
|
||||
table.Add("name", "小明");
|
||||
table.Add("age", 18);
|
||||
|
||||
foreach (DictionaryEntry item in table)
|
||||
{
|
||||
Console.WriteLine(item.Key + " : " + item.Value);
|
||||
}
|
||||
```
|
||||
|
||||
只遍历键:
|
||||
```csharp
|
||||
foreach (object key in table.Keys)
|
||||
{
|
||||
Console.WriteLine(key);
|
||||
}
|
||||
```
|
||||
|
||||
只遍历值:
|
||||
```csharp
|
||||
foreach (object value in table.Values)
|
||||
{
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
```
|
||||
|
||||
注意:
|
||||
`Hashtable` 的遍历顺序不保证等于添加顺序
|
||||
|
||||
----
|
||||
# key 不能重复
|
||||
错误写法:
|
||||
```csharp
|
||||
Hashtable table = new Hashtable();
|
||||
|
||||
table.Add("name", "小明");
|
||||
table.Add("name", "小红");
|
||||
```
|
||||
|
||||
原因:
|
||||
`Hashtable` 中的 key 必须唯一
|
||||
重复添加同一个 key 会报错
|
||||
|
||||
如果想修改旧值:
|
||||
```csharp
|
||||
table["name"] = "小红";
|
||||
```
|
||||
|
||||
----
|
||||
# key 不能是 null
|
||||
错误写法:
|
||||
```csharp
|
||||
Hashtable table = new Hashtable();
|
||||
|
||||
table.Add(null, "值");
|
||||
```
|
||||
|
||||
原因:
|
||||
`Hashtable` 的 key 不能为 `null`
|
||||
|
||||
但是 value 可以是 `null`:
|
||||
```csharp
|
||||
table.Add("data", null);
|
||||
```
|
||||
|
||||
----
|
||||
# 取值时要判断 key 是否存在
|
||||
```csharp
|
||||
Hashtable table = new Hashtable();
|
||||
table.Add("name", "小明");
|
||||
|
||||
if (table.ContainsKey("name"))
|
||||
{
|
||||
string name = (string)table["name"];
|
||||
Console.WriteLine(name);
|
||||
}
|
||||
```
|
||||
|
||||
为什么要判断:
|
||||
1. key 不存在时,`table[key]` 可能拿到 `null`
|
||||
2. value 本身也可能是 `null`
|
||||
3. 用 `ContainsKey` 可以区分“没有这个键”和“这个键的值是 null”
|
||||
|
||||
----
|
||||
# 取值时要类型转换
|
||||
```csharp
|
||||
Hashtable table = new Hashtable();
|
||||
table.Add("age", 18);
|
||||
|
||||
int age = (int)table["age"];
|
||||
```
|
||||
|
||||
原因:
|
||||
非泛型 `Hashtable` 的 key 和 value 都是按 `object` 处理
|
||||
取出来后通常需要强制类型转换
|
||||
|
||||
如果类型转错:
|
||||
```csharp
|
||||
string age = (string)table["age"];
|
||||
```
|
||||
|
||||
会出错,因为 `"age"` 对应的值实际是 `int`。
|
||||
|
||||
----
|
||||
# 和 ArrayList 的区别
|
||||
| 对比点 | ArrayList | Hashtable |
|
||||
|---|---|---|
|
||||
| 存储方式 | 单个元素 | 键值对 |
|
||||
| 访问方式 | 通过下标 | 通过 key |
|
||||
| key 是否存在 | 没有 key | key 必须唯一 |
|
||||
| 常见用途 | 普通列表 | 字典式查找 |
|
||||
| 泛型替代 | `List<T>` | `Dictionary<TKey, TValue>` |
|
||||
|
||||
----
|
||||
# 常见错误
|
||||
错误1:重复 Add 同一个 key
|
||||
```csharp
|
||||
table.Add("id", 1);
|
||||
table.Add("id", 2);
|
||||
```
|
||||
|
||||
应该改成:
|
||||
```csharp
|
||||
table["id"] = 2;
|
||||
```
|
||||
|
||||
----
|
||||
错误2:以为 Hashtable 有添加顺序
|
||||
|
||||
实际:
|
||||
`Hashtable` 是根据 key 的哈希来组织数据
|
||||
遍历顺序不保证是添加顺序
|
||||
|
||||
----
|
||||
错误3:取值后忘记强转
|
||||
```csharp
|
||||
int age = table["age"];
|
||||
```
|
||||
|
||||
应该写:
|
||||
```csharp
|
||||
int age = (int)table["age"];
|
||||
```
|
||||
|
||||
----
|
||||
# 注意
|
||||
1. `Hashtable` 在 `System.Collections` 命名空间中
|
||||
2. `Hashtable` 是非泛型键值对集合
|
||||
3. key 不能重复
|
||||
4. key 不能是 `null`
|
||||
5. value 可以是 `null`
|
||||
6. `Add` 重复 key 会报错
|
||||
7. `table[key] = value` 可以新增,也可以覆盖旧值
|
||||
8. 遍历顺序不保证等于添加顺序
|
||||
9. 新项目通常优先使用 `Dictionary<TKey, TValue>`
|
||||
|
||||
----
|
||||
# 一句话记忆
|
||||
==Hashtable 是用 key 找 value 的非泛型键值对集合。==
|
||||
|
||||
再压缩一点:
|
||||
==ArrayList 靠下标找,Hashtable 靠 key 找。==
|
||||
|
||||
----
|
||||
# 面试/复习时怎么说
|
||||
可以这样答:
|
||||
|
||||
“Hashtable 是 `System.Collections` 命名空间下的非泛型键值对集合,通过唯一 key 查找 value。
|
||||
它的 key 不能重复,也不能为 null;value 可以为 null。
|
||||
因为 key 和 value 都按 object 处理,所以取值时通常需要强制类型转换。新项目中一般更推荐使用泛型集合 `Dictionary<TKey, TValue>`。”
|
||||
|
||||
----
|
||||
引用:
|
||||
1. Microsoft Learn: [Hashtable Class](https://learn.microsoft.com/dotnet/api/system.collections.hashtable?view=net-9.0)
|
||||
2. Microsoft Learn: [Hashtable.Add Method](https://learn.microsoft.com/en-us/dotnet/api/system.collections.hashtable.add?view=net-9.0)
|
||||
3. Microsoft Learn: [Hashtable.Item Property](https://learn.microsoft.com/en-us/dotnet/api/system.collections.hashtable.item?view=net-9.0)
|
||||
4. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)
|
||||
|
||||
#Hashtable
|
||||
#哈希表
|
||||
#集合
|
||||
#进阶
|
||||
@@ -0,0 +1,279 @@
|
||||
# Queue
|
||||
概念:
|
||||
`Queue` 是 C# 提供的一个==非泛型队列集合==
|
||||
队列的特点是:==先进先出==
|
||||
|
||||
英文:
|
||||
`FIFO`:First In First Out
|
||||
|
||||
简单理解:
|
||||
像排队买东西
|
||||
先排队的人,先被处理
|
||||
|
||||
命名空间:
|
||||
```csharp
|
||||
using System.Collections;
|
||||
```
|
||||
|
||||
----
|
||||
# 通常用法
|
||||
1. 处理需要“按进入顺序依次处理”的数据
|
||||
2. 保存等待处理的任务
|
||||
3. 模拟排队、消息、请求等逻辑
|
||||
4. 学习队列这种数据结构
|
||||
|
||||
实际开发中:
|
||||
新代码更推荐使用 `Queue<T>`
|
||||
这里的 `Queue` 是非泛型版本
|
||||
|
||||
----
|
||||
# 语法
|
||||
创建:
|
||||
```csharp
|
||||
Queue queue = new Queue();
|
||||
```
|
||||
|
||||
入队:
|
||||
```csharp
|
||||
queue.Enqueue(数据);
|
||||
```
|
||||
|
||||
出队:
|
||||
```csharp
|
||||
object value = queue.Dequeue();
|
||||
```
|
||||
|
||||
查看队头:
|
||||
```csharp
|
||||
object value = queue.Peek();
|
||||
```
|
||||
|
||||
数量:
|
||||
```csharp
|
||||
queue.Count
|
||||
```
|
||||
|
||||
----
|
||||
# 基础案例
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
Queue queue = new Queue();
|
||||
|
||||
queue.Enqueue("第一个任务");
|
||||
queue.Enqueue("第二个任务");
|
||||
queue.Enqueue("第三个任务");
|
||||
|
||||
Console.WriteLine(queue.Dequeue());
|
||||
Console.WriteLine(queue.Dequeue());
|
||||
Console.WriteLine(queue.Dequeue());
|
||||
```
|
||||
|
||||
输出:
|
||||
```text
|
||||
第一个任务
|
||||
第二个任务
|
||||
第三个任务
|
||||
```
|
||||
|
||||
理解:
|
||||
1. `"第一个任务"` 最先进队列
|
||||
2. `Dequeue()` 会先取出最早进入队列的元素
|
||||
3. 这就是先进先出
|
||||
|
||||
----
|
||||
# Enqueue、Dequeue、Peek
|
||||
`Enqueue`:
|
||||
把元素添加到队尾
|
||||
|
||||
```csharp
|
||||
queue.Enqueue("A");
|
||||
```
|
||||
|
||||
`Dequeue`:
|
||||
取出并删除队头元素
|
||||
|
||||
```csharp
|
||||
object item = queue.Dequeue();
|
||||
```
|
||||
|
||||
`Peek`:
|
||||
查看队头元素,但不删除
|
||||
|
||||
```csharp
|
||||
object item = queue.Peek();
|
||||
```
|
||||
|
||||
案例:
|
||||
```csharp
|
||||
Queue queue = new Queue();
|
||||
queue.Enqueue("A");
|
||||
queue.Enqueue("B");
|
||||
|
||||
Console.WriteLine(queue.Peek()); // A
|
||||
Console.WriteLine(queue.Count); // 2
|
||||
|
||||
Console.WriteLine(queue.Dequeue()); // A
|
||||
Console.WriteLine(queue.Count); // 1
|
||||
```
|
||||
|
||||
----
|
||||
# 遍历
|
||||
```csharp
|
||||
Queue queue = new Queue();
|
||||
|
||||
queue.Enqueue("A");
|
||||
queue.Enqueue("B");
|
||||
queue.Enqueue("C");
|
||||
|
||||
foreach (object item in queue)
|
||||
{
|
||||
Console.WriteLine(item);
|
||||
}
|
||||
```
|
||||
|
||||
输出顺序一般是:
|
||||
```text
|
||||
A
|
||||
B
|
||||
C
|
||||
```
|
||||
|
||||
理解:
|
||||
遍历 `Queue` 时,通常按入队顺序从队头到队尾遍历
|
||||
|
||||
----
|
||||
# 常用成员
|
||||
```csharp
|
||||
Queue queue = new Queue();
|
||||
|
||||
queue.Enqueue("A");
|
||||
queue.Enqueue("B");
|
||||
|
||||
Console.WriteLine(queue.Count);
|
||||
Console.WriteLine(queue.Contains("A"));
|
||||
|
||||
object first = queue.Peek();
|
||||
object value = queue.Dequeue();
|
||||
|
||||
queue.Clear();
|
||||
```
|
||||
|
||||
常用方法:
|
||||
1. `Enqueue(object obj)`:入队
|
||||
2. `Dequeue()`:出队并删除
|
||||
3. `Peek()`:查看队头但不删除
|
||||
4. `Contains(object obj)`:判断是否包含
|
||||
5. `Clear()`:清空
|
||||
6. `ToArray()`:转成数组
|
||||
|
||||
----
|
||||
# 空队列不能 Dequeue 或 Peek
|
||||
错误写法:
|
||||
```csharp
|
||||
Queue queue = new Queue();
|
||||
|
||||
queue.Dequeue();
|
||||
```
|
||||
|
||||
原因:
|
||||
队列里没有元素,不能取队头
|
||||
|
||||
更稳的写法:
|
||||
```csharp
|
||||
if (queue.Count > 0)
|
||||
{
|
||||
object value = queue.Dequeue();
|
||||
}
|
||||
```
|
||||
|
||||
`Peek()` 也一样,使用前最好先判断 `Count`。
|
||||
|
||||
----
|
||||
# 取值时要类型转换
|
||||
```csharp
|
||||
Queue queue = new Queue();
|
||||
queue.Enqueue(100);
|
||||
|
||||
int num = (int)queue.Dequeue();
|
||||
```
|
||||
|
||||
原因:
|
||||
非泛型 `Queue` 中的元素按 `object` 存储
|
||||
取出来也是 `object`
|
||||
|
||||
值类型入队和出队时,也会涉及装箱拆箱:
|
||||
```csharp
|
||||
queue.Enqueue(100); // 装箱
|
||||
int num = (int)queue.Dequeue(); // 拆箱
|
||||
```
|
||||
|
||||
----
|
||||
# 适合场景:任务队列
|
||||
```csharp
|
||||
Queue taskQueue = new Queue();
|
||||
|
||||
taskQueue.Enqueue("加载配置");
|
||||
taskQueue.Enqueue("读取存档");
|
||||
taskQueue.Enqueue("进入场景");
|
||||
|
||||
while (taskQueue.Count > 0)
|
||||
{
|
||||
string task = (string)taskQueue.Dequeue();
|
||||
Console.WriteLine("处理:" + task);
|
||||
}
|
||||
```
|
||||
|
||||
理解:
|
||||
任务按照加入顺序依次处理
|
||||
这种情况适合用队列
|
||||
|
||||
----
|
||||
# Queue 和 Stack 的区别
|
||||
| 对比点 | Queue | Stack |
|
||||
|---|---|---|
|
||||
| 规则 | 先进先出 | 后进先出 |
|
||||
| 英文 | FIFO | LIFO |
|
||||
| 添加 | `Enqueue` | `Push` |
|
||||
| 取出 | `Dequeue` | `Pop` |
|
||||
| 查看 | `Peek` 查看队头 | `Peek` 查看栈顶 |
|
||||
| 适合场景 | 排队处理任务 | 撤销、回退 |
|
||||
|
||||
一句话:
|
||||
排队用 `Queue`
|
||||
回退用 `Stack`
|
||||
|
||||
----
|
||||
# 注意
|
||||
1. `Queue` 在 `System.Collections` 命名空间中
|
||||
2. `Queue` 是非泛型集合,元素按 `object` 存储
|
||||
3. 队列的规则是先进先出
|
||||
4. `Enqueue` 是入队
|
||||
5. `Dequeue` 是出队并删除队头
|
||||
6. `Peek` 是查看队头但不删除
|
||||
7. 空队列调用 `Dequeue()` 或 `Peek()` 会出错
|
||||
8. 新项目通常优先使用 `Queue<T>`
|
||||
|
||||
----
|
||||
# 一句话记忆
|
||||
==Queue 是先进先出的集合,先进去的先出来。==
|
||||
|
||||
----
|
||||
# 面试/复习时怎么说
|
||||
可以这样答:
|
||||
|
||||
“Queue 是队列结构,特点是先进先出,也就是 FIFO。
|
||||
常用方法有 `Enqueue`、`Dequeue` 和 `Peek`,分别表示入队、出队、查看队头。
|
||||
非泛型 Queue 存的是 object,取值时可能需要强制类型转换,新项目中更推荐使用 `Queue<T>`。”
|
||||
|
||||
----
|
||||
引用:
|
||||
1. Microsoft Learn: [Queue Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.queue?view=net-9.0)
|
||||
2. Microsoft Learn: [Queue.Enqueue Method](https://learn.microsoft.com/en-us/dotnet/api/system.collections.queue.enqueue?view=net-9.0)
|
||||
3. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)
|
||||
|
||||
#Queue
|
||||
#队列
|
||||
#集合
|
||||
#进阶
|
||||
@@ -0,0 +1,273 @@
|
||||
# Stack
|
||||
概念:
|
||||
`Stack` 是 C# 提供的一个==非泛型栈集合==
|
||||
栈的特点是:==先进后出,后进先出==
|
||||
|
||||
英文:
|
||||
`LIFO`:Last In First Out
|
||||
|
||||
简单理解:
|
||||
像一摞盘子
|
||||
最后放上去的,最先被拿走
|
||||
|
||||
命名空间:
|
||||
```csharp
|
||||
using System.Collections;
|
||||
```
|
||||
|
||||
----
|
||||
# 通常用法
|
||||
1. 处理需要“后进先出”的数据
|
||||
2. 临时保存操作记录
|
||||
3. 实现撤销、回退、调用顺序等逻辑
|
||||
4. 学习栈这种数据结构
|
||||
|
||||
实际开发中:
|
||||
新代码更推荐使用 `Stack<T>`
|
||||
这里的 `Stack` 是非泛型版本,主要用于理解集合和数据结构
|
||||
|
||||
----
|
||||
# 语法
|
||||
创建:
|
||||
```csharp
|
||||
Stack stack = new Stack();
|
||||
```
|
||||
|
||||
入栈:
|
||||
```csharp
|
||||
stack.Push(数据);
|
||||
```
|
||||
|
||||
出栈:
|
||||
```csharp
|
||||
object value = stack.Pop();
|
||||
```
|
||||
|
||||
查看栈顶:
|
||||
```csharp
|
||||
object value = stack.Peek();
|
||||
```
|
||||
|
||||
数量:
|
||||
```csharp
|
||||
stack.Count
|
||||
```
|
||||
|
||||
----
|
||||
# 基础案例
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
Stack stack = new Stack();
|
||||
|
||||
stack.Push("第一步");
|
||||
stack.Push("第二步");
|
||||
stack.Push("第三步");
|
||||
|
||||
Console.WriteLine(stack.Pop());
|
||||
Console.WriteLine(stack.Pop());
|
||||
Console.WriteLine(stack.Pop());
|
||||
```
|
||||
|
||||
输出:
|
||||
```text
|
||||
第三步
|
||||
第二步
|
||||
第一步
|
||||
```
|
||||
|
||||
理解:
|
||||
1. `"第一步"` 最先进栈
|
||||
2. `"第三步"` 最后进栈
|
||||
3. `Pop()` 会先取出最后进去的元素
|
||||
|
||||
----
|
||||
# Push、Pop、Peek
|
||||
`Push`:
|
||||
把元素放到栈顶
|
||||
|
||||
```csharp
|
||||
stack.Push("A");
|
||||
```
|
||||
|
||||
`Pop`:
|
||||
取出并删除栈顶元素
|
||||
|
||||
```csharp
|
||||
object item = stack.Pop();
|
||||
```
|
||||
|
||||
`Peek`:
|
||||
只查看栈顶元素,不删除
|
||||
|
||||
```csharp
|
||||
object item = stack.Peek();
|
||||
```
|
||||
|
||||
案例:
|
||||
```csharp
|
||||
Stack stack = new Stack();
|
||||
stack.Push("A");
|
||||
stack.Push("B");
|
||||
|
||||
Console.WriteLine(stack.Peek()); // B
|
||||
Console.WriteLine(stack.Count); // 2
|
||||
|
||||
Console.WriteLine(stack.Pop()); // B
|
||||
Console.WriteLine(stack.Count); // 1
|
||||
```
|
||||
|
||||
----
|
||||
# 遍历
|
||||
```csharp
|
||||
Stack stack = new Stack();
|
||||
|
||||
stack.Push("A");
|
||||
stack.Push("B");
|
||||
stack.Push("C");
|
||||
|
||||
foreach (object item in stack)
|
||||
{
|
||||
Console.WriteLine(item);
|
||||
}
|
||||
```
|
||||
|
||||
输出顺序一般是:
|
||||
```text
|
||||
C
|
||||
B
|
||||
A
|
||||
```
|
||||
|
||||
理解:
|
||||
遍历 `Stack` 时,也是从栈顶到栈底
|
||||
|
||||
----
|
||||
# 常用成员
|
||||
```csharp
|
||||
Stack stack = new Stack();
|
||||
|
||||
stack.Push("A");
|
||||
stack.Push("B");
|
||||
|
||||
Console.WriteLine(stack.Count);
|
||||
Console.WriteLine(stack.Contains("A"));
|
||||
|
||||
object top = stack.Peek();
|
||||
object value = stack.Pop();
|
||||
|
||||
stack.Clear();
|
||||
```
|
||||
|
||||
常用方法:
|
||||
1. `Push(object obj)`:入栈
|
||||
2. `Pop()`:出栈并删除
|
||||
3. `Peek()`:查看栈顶但不删除
|
||||
4. `Contains(object obj)`:判断是否包含
|
||||
5. `Clear()`:清空
|
||||
6. `ToArray()`:转成数组
|
||||
|
||||
----
|
||||
# 空栈不能 Pop 或 Peek
|
||||
错误写法:
|
||||
```csharp
|
||||
Stack stack = new Stack();
|
||||
|
||||
stack.Pop();
|
||||
```
|
||||
|
||||
原因:
|
||||
栈里没有元素,不能取栈顶
|
||||
|
||||
更稳的写法:
|
||||
```csharp
|
||||
if (stack.Count > 0)
|
||||
{
|
||||
object value = stack.Pop();
|
||||
}
|
||||
```
|
||||
|
||||
`Peek()` 也一样,使用前最好先判断 `Count`。
|
||||
|
||||
----
|
||||
# 取值时要类型转换
|
||||
```csharp
|
||||
Stack stack = new Stack();
|
||||
stack.Push(100);
|
||||
|
||||
int num = (int)stack.Pop();
|
||||
```
|
||||
|
||||
原因:
|
||||
非泛型 `Stack` 中的元素按 `object` 存储
|
||||
取出来也是 `object`
|
||||
|
||||
如果值类型放进去,会涉及装箱和拆箱:
|
||||
```csharp
|
||||
stack.Push(100); // 装箱
|
||||
int num = (int)stack.Pop(); // 拆箱
|
||||
```
|
||||
|
||||
----
|
||||
# 适合场景:撤销操作
|
||||
```csharp
|
||||
Stack undoStack = new Stack();
|
||||
|
||||
undoStack.Push("创建角色");
|
||||
undoStack.Push("移动角色");
|
||||
undoStack.Push("修改颜色");
|
||||
|
||||
if (undoStack.Count > 0)
|
||||
{
|
||||
string lastAction = (string)undoStack.Pop();
|
||||
Console.WriteLine("撤销:" + lastAction);
|
||||
}
|
||||
```
|
||||
|
||||
理解:
|
||||
最后做的操作,通常最先撤销
|
||||
所以适合用栈
|
||||
|
||||
----
|
||||
# Stack 和 ArrayList 的区别
|
||||
| 对比点 | ArrayList | Stack |
|
||||
|---|---|---|
|
||||
| 访问方式 | 按下标访问 | 只关心栈顶 |
|
||||
| 数据顺序 | 按添加顺序保存 | 后进先出 |
|
||||
| 添加方法 | `Add` | `Push` |
|
||||
| 取出方法 | `list[index]` | `Pop` / `Peek` |
|
||||
| 适合场景 | 普通列表 | 回退、撤销、临时反向处理 |
|
||||
|
||||
----
|
||||
# 注意
|
||||
1. `Stack` 在 `System.Collections` 命名空间中
|
||||
2. `Stack` 是非泛型集合,元素按 `object` 存储
|
||||
3. 栈的规则是后进先出
|
||||
4. `Push` 是入栈
|
||||
5. `Pop` 是取出并删除栈顶
|
||||
6. `Peek` 是查看栈顶但不删除
|
||||
7. 空栈调用 `Pop()` 或 `Peek()` 会出错
|
||||
8. 新项目通常优先使用 `Stack<T>`
|
||||
|
||||
----
|
||||
# 一句话记忆
|
||||
==Stack 是后进先出的集合,最后放进去的最先出来。==
|
||||
|
||||
----
|
||||
# 面试/复习时怎么说
|
||||
可以这样答:
|
||||
|
||||
“Stack 是栈结构,特点是后进先出,也就是 LIFO。
|
||||
常用方法有 `Push`、`Pop` 和 `Peek`,分别表示入栈、出栈、查看栈顶。
|
||||
非泛型 Stack 存的是 object,取值时可能需要强制类型转换,新项目中更推荐使用 `Stack<T>`。”
|
||||
|
||||
----
|
||||
引用:
|
||||
1. Microsoft Learn: [Stack Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.stack?view=net-9.0)
|
||||
2. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)
|
||||
|
||||
#Stack
|
||||
#栈
|
||||
#集合
|
||||
#进阶
|
||||
@@ -0,0 +1,380 @@
|
||||
# 泛型
|
||||
|
||||
概念:
|
||||
泛型就是把==类型==参数化,让一份代码可以适配多种数据类型。
|
||||
可以理解为:先把类型空出来,等使用时再指定具体类型。
|
||||
|
||||
例如:
|
||||
```csharp
|
||||
List<int> nums = new List<int>();
|
||||
List<string> names = new List<string>();
|
||||
```
|
||||
|
||||
其中 `int` 和 `string` 就是传入泛型的具体类型。
|
||||
|
||||
----
|
||||
# 为什么需要泛型
|
||||
|
||||
泛型的主要作用:
|
||||
1. 提高代码复用性
|
||||
2. 保证类型安全
|
||||
3. 减少强制类型转换
|
||||
4. 避免不必要的装箱和拆箱
|
||||
|
||||
对比 `ArrayList`:
|
||||
```csharp
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add(1);
|
||||
list.Add("hello");
|
||||
|
||||
int num = (int)list[0];
|
||||
```
|
||||
|
||||
`ArrayList` 内部存的是 `object`,取值时经常需要强制转换。
|
||||
|
||||
使用泛型集合:
|
||||
```csharp
|
||||
List<int> list = new List<int>();
|
||||
list.Add(1);
|
||||
|
||||
int num = list[0];
|
||||
```
|
||||
|
||||
`List<int>` 只能存 `int`,编译器会提前帮我们检查类型错误。
|
||||
|
||||
----
|
||||
# 常见泛型形式
|
||||
|
||||
泛型可以用于:
|
||||
1. 泛型类
|
||||
2. 泛型接口
|
||||
3. 泛型方法
|
||||
4. 泛型委托
|
||||
5. 泛型集合
|
||||
|
||||
常见泛型集合:
|
||||
```csharp
|
||||
List<T>
|
||||
Dictionary<TKey, TValue>
|
||||
Queue<T>
|
||||
Stack<T>
|
||||
HashSet<T>
|
||||
```
|
||||
|
||||
`T`、`TKey`、`TValue` 都是泛型类型参数名。
|
||||
|
||||
----
|
||||
# 语法
|
||||
|
||||
泛型类:
|
||||
```csharp
|
||||
class 类名<T>
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
泛型接口:
|
||||
```csharp
|
||||
interface 接口名<T>
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
泛型方法:
|
||||
```csharp
|
||||
返回值类型 方法名<T>(T 参数)
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
多个泛型类型参数:
|
||||
```csharp
|
||||
class 类名<T1, T2>
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
----
|
||||
# 泛型类
|
||||
|
||||
泛型类适合用来保存或处理某种不确定类型的数据。
|
||||
|
||||
```csharp
|
||||
class Box<T>
|
||||
{
|
||||
public T Value { get; set; }
|
||||
|
||||
public Box(T value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public T GetValue()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
使用:
|
||||
```csharp
|
||||
Box<int> intBox = new Box<int>(10);
|
||||
Console.WriteLine(intBox.GetValue());
|
||||
|
||||
Box<string> stringBox = new Box<string>("hello");
|
||||
Console.WriteLine(stringBox.GetValue());
|
||||
```
|
||||
|
||||
理解:
|
||||
1. `Box<T>` 定义时不知道 `T` 是什么类型
|
||||
2. `Box<int>` 使用时把 `T` 替换成 `int`
|
||||
3. `Box<string>` 使用时把 `T` 替换成 `string`
|
||||
|
||||
----
|
||||
# 泛型接口
|
||||
|
||||
泛型接口常用于规定一类对象必须提供某种泛型能力。
|
||||
|
||||
```csharp
|
||||
interface IRepository<T>
|
||||
{
|
||||
void Add(T item);
|
||||
T Get(int index);
|
||||
}
|
||||
```
|
||||
|
||||
实现:
|
||||
```csharp
|
||||
class MemoryRepository<T> : IRepository<T>
|
||||
{
|
||||
private List<T> items = new List<T>();
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
items.Add(item);
|
||||
}
|
||||
|
||||
public T Get(int index)
|
||||
{
|
||||
return items[index];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
使用:
|
||||
```csharp
|
||||
IRepository<string> repository = new MemoryRepository<string>();
|
||||
|
||||
repository.Add("小明");
|
||||
Console.WriteLine(repository.Get(0));
|
||||
```
|
||||
|
||||
----
|
||||
# 泛型方法
|
||||
|
||||
泛型方法适合处理“逻辑一样,但参数类型不同”的情况。
|
||||
|
||||
```csharp
|
||||
static void Print<T>(T value)
|
||||
{
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
```
|
||||
|
||||
使用:
|
||||
```csharp
|
||||
Print<int>(100);
|
||||
Print<string>("hello");
|
||||
Print<bool>(true);
|
||||
```
|
||||
|
||||
很多时候,编译器可以自动推断泛型类型:
|
||||
```csharp
|
||||
Print(100);
|
||||
Print("hello");
|
||||
Print(true);
|
||||
```
|
||||
|
||||
----
|
||||
# 泛型约束
|
||||
|
||||
默认情况下,泛型类型 `T` 可以是任意类型。
|
||||
|
||||
如果希望限制 `T` 必须满足某些条件,可以使用 `where` 约束。
|
||||
|
||||
语法:
|
||||
```csharp
|
||||
class 类名<T> where T : 约束
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
常见约束:
|
||||
|
||||
| 约束 | 含义 |
|
||||
| --- | --- |
|
||||
| `where T : class` | `T` 必须是引用类型 |
|
||||
| `where T : struct` | `T` 必须是值类型 |
|
||||
| `where T : new()` | `T` 必须有无参构造函数 |
|
||||
| `where T : 父类名` | `T` 必须继承某个父类 |
|
||||
| `where T : 接口名` | `T` 必须实现某个接口 |
|
||||
|
||||
案例:
|
||||
```csharp
|
||||
class Factory<T> where T : new()
|
||||
{
|
||||
public T Create()
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
因为加了 `where T : new()`,所以可以在类中使用 `new T()`。
|
||||
|
||||
----
|
||||
# 多泛型参数
|
||||
|
||||
一个类或方法可以同时使用多个泛型参数。
|
||||
|
||||
```csharp
|
||||
class Pair<TKey, TValue>
|
||||
{
|
||||
public TKey Key { get; set; }
|
||||
public TValue Value { get; set; }
|
||||
|
||||
public Pair(TKey key, TValue value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
使用:
|
||||
```csharp
|
||||
Pair<int, string> pair = new Pair<int, string>(1, "小明");
|
||||
|
||||
Console.WriteLine(pair.Key);
|
||||
Console.WriteLine(pair.Value);
|
||||
```
|
||||
|
||||
----
|
||||
# default 关键字
|
||||
|
||||
泛型中有时不知道 `T` 的默认值是什么,可以使用 `default`。
|
||||
|
||||
```csharp
|
||||
static T GetDefault<T>()
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
```
|
||||
|
||||
常见默认值:
|
||||
|
||||
| 类型 | 默认值 |
|
||||
| --- | --- |
|
||||
| `int` | `0` |
|
||||
| `bool` | `false` |
|
||||
| 引用类型 | `null` |
|
||||
| 结构体 | 所有字段都是默认值 |
|
||||
|
||||
新语法也可以写成:
|
||||
```csharp
|
||||
return default;
|
||||
```
|
||||
|
||||
----
|
||||
# 完整案例
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GenericsDemo
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
DataStore<int> intStore = new DataStore<int>();
|
||||
intStore.Add(10);
|
||||
intStore.Add(20);
|
||||
|
||||
Console.WriteLine(intStore.Get(0));
|
||||
Console.WriteLine(intStore.Get(1));
|
||||
|
||||
DataStore<string> stringStore = new DataStore<string>();
|
||||
stringStore.Add("hello");
|
||||
stringStore.Add("world");
|
||||
|
||||
Console.WriteLine(stringStore.Get(0));
|
||||
Console.WriteLine(stringStore.Get(1));
|
||||
|
||||
Print(123);
|
||||
Print("泛型方法");
|
||||
}
|
||||
|
||||
static void Print<T>(T value)
|
||||
{
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
interface IDataStore<T>
|
||||
{
|
||||
void Add(T value);
|
||||
T Get(int index);
|
||||
}
|
||||
|
||||
class DataStore<T> : IDataStore<T>
|
||||
{
|
||||
private List<T> values = new List<T>();
|
||||
|
||||
public void Add(T value)
|
||||
{
|
||||
values.Add(value);
|
||||
}
|
||||
|
||||
public T Get(int index)
|
||||
{
|
||||
return values[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
理解:
|
||||
1. `DataStore<T>` 是泛型类
|
||||
2. `IDataStore<T>` 是泛型接口
|
||||
3. `Print<T>` 是泛型方法
|
||||
4. `DataStore<int>` 只能保存整数
|
||||
5. `DataStore<string>` 只能保存字符串
|
||||
|
||||
----
|
||||
# 注意
|
||||
|
||||
1. 泛型类型参数常用 `T` 表示,但不是固定写法
|
||||
2. 多个泛型参数常写成 `TKey`、`TValue`、`TItem`
|
||||
3. `List<T>` 比 `ArrayList` 更常用,也更安全
|
||||
4. 泛型在编译期就能检查类型错误
|
||||
5. 使用泛型可以减少 `object` 带来的强制转换
|
||||
6. 如果需要在泛型中 `new T()`,必须加 `where T : new()` 约束
|
||||
7. 泛型不是“任何类型都乱放”,而是“使用时确定一种类型”
|
||||
|
||||
----
|
||||
# 小结
|
||||
|
||||
一句话:
|
||||
泛型就是==把类型当作参数传进去==。
|
||||
|
||||
记忆:
|
||||
普通参数控制“值”。
|
||||
泛型参数控制“类型”。
|
||||
|
||||
最常见写法:
|
||||
```csharp
|
||||
List<int> nums = new List<int>();
|
||||
Dictionary<string, int> scores = new Dictionary<string, int>();
|
||||
```
|
||||
Reference in New Issue
Block a user