第 8 课 · 约 12 分钟 · ← 第 7 课
集合:数组、List、Dictionary
几乎所有程序都是"装一堆东西,然后对它们做点什么"。C# 的三匹主力马覆盖其中 95%:数组(定长、最快)、List<T>(可增长)、Dictionary(按键查找)。
数组:一排格子,出生时定死数量
int[] scores = new int[3]; // 恰好 3 个槽,现在决定
scores[0] = 72;
scores[1] = 95;
scores[2] = 88;
int total = 0;
for (int i = 0; i < scores.Length; i++) // 数组用 .Length
{
total += scores[i];
}
Console.WriteLine("total: " + total + " count: " + scores.Length);
下标从 0 开始,最后一格是 Length - 1——越过去运行时就会收到 IndexOutOfRangeException。知道值时的短写法:int[] scores = { 72, 95, 88 };
List<T>:同一排格子,按需增长
var names = new List();
names.Add("Ada");
names.Add("Grace");
names.Add("Linus");
Console.WriteLine(names.Count); // List 用 .Count,不是 .Length
names.RemoveAt(0); // 按下标删——数组做不到这个
Console.WriteLine(string.Join(", ", names));
<string> 是类型实参:这个列表装字符串,编译器强制执行。Add、Remove、Contains、IndexOf、Sort、Reverse——日常工具箱。注意这里是 .Count,数组是 .Length;搞混了也无妨,错误消息会提醒你(CS1061)。
Dictionary:没有下标——按 KEY 查
var ages = new Dictionary(); // 键是 string,值是 int
ages["Ada"] = 36; // 按键添加或更新
ages["Grace"] = 45;
Console.WriteLine(ages["Ada"] + ages["Grace"]);
foreach (string k in ages.Keys) // 遍历键
{
Console.WriteLine(k + " -> " + ages[k]);
}
if (ages.TryGetValue("Linus", out int age)) // 安全查找
{
Console.WriteLine(age);
}
else
{
Console.WriteLine("Linus not found");
}
一个陷阱:用 ages["Linus"] 读不存在的键会抛出 KeyNotFoundException——这正是 TryGetValue 存在的原因。它是字典版的 int.TryParse:试着查,按成败分支。
foreach 对三者通吃
int[] arr = { 72, 95, 88 };
var list = new List { 1, 2, 3 };
foreach (int x in arr) Console.Write(x + " ");
foreach (int x in list) Console.Write(x + " ");
(字典在本引擎里需要 foreach 遍历 .Keys/.Values——成对遍历的 KeyValuePair 在路线图上。)
哪个,什么时候?
| 需求 | 用 | 为什么 |
|---|---|---|
| 固定槽位、下标运算、性能 | T[] | 最小、最快、不可增删 |
| "一堆东西"要增要删 | List<T> | 现代 C# 的默认选择 |
| 按名字/ID 查,不按位置 | Dictionary<K,V> | 按键即时查找 |
| 只遍历一次 | 任意 + foreach | 根本不需要下标 |
现在就练
- 建一个 5 个成绩的
List<int>,打印平均值(double)——除的时候留意整数除法陷阱。 - 建字典:3 个用户名对分数;全部打印,再安全地查一个不存在的。
- 下一课:第 9 课 — 异常。