本课学习目标
- 理解为什么程序需要集合(Collection)保存多项数据。
- 建立并使用一维数组。
- 理解数组索引从 0 开始。
- 使用 Length 取得数组元素数量。
- 使用 For 与 For Each 遍历集合。
- 建立 List(Of T) 泛型列表。
- 使用 Add、Remove、RemoveAt、Clear。
- 使用 Count 与 Contains。
- 理解数组和 List(Of T) 的主要区别。
- 使用 List(Of Student) 保存对象。
- 完成学生列表管理器。
16.1 为什么需要保存多项数据?
如果有 30 名学生,建立 student1、student2、student3……student30 并不是好设计。我们需要一种能够统一保存多项数据的结构。
score As Integer
只保存一个成绩。
scores() As Integer
保存固定的一组 Integer。
List(Of Integer)
保存可动态增加或删除的一组 Integer。
16.2 什么是数组?
数组是一组相同类型的元素。最简单的建立方式:
Dim scores() As Integer = {78, 85, 92, 66, 88}
这一个变量中保存了 5 个 Integer。
16.3 读取与修改数组元素
Dim scores() As Integer = {78, 85, 92, 66, 88}
Dim firstScore As Integer = scores(0)
Dim thirdScore As Integer = scores(2)
scores(3) = 70
修改后,第 4 个元素由 66 变成 70。
16.4 使用 Length
数组的 Length 属性返回元素数量:
Dim scores() As Integer = {78, 85, 92, 66, 88}
Dim itemCount As Integer = scores.Length
结果为 5。
由于索引从 0 开始,最后一个有效索引通常是:
scores.Length - 1
16.5 使用 For 遍历数组
Dim scores() As Integer = {78, 85, 92, 66, 88}
For index As Integer = 0 To scores.Length - 1
txtOutput.Text &=
$"索引 {index}:{scores(index)}" &
Environment.NewLine
Next
For 的优点是同时能够使用当前索引。
16.6 使用 For Each
如果只需要逐项处理,而不关心索引,For Each 更简洁:
Dim scores() As Integer = {78, 85, 92, 66, 88}
For Each score As Integer In scores
txtOutput.Text &=
score.ToString() &
Environment.NewLine
Next
适合需要索引、倒序处理或特定位置操作。
适合只需要“逐个元素处理”的情况,代码更自然。
16.7 用数组计算总和与平均分
Dim scores() As Integer = {78, 85, 92, 66, 88}
Dim total As Integer = 0
For Each score As Integer In scores
total += score
Next
Dim average As Double =
total / CDbl(scores.Length)
lblResult.Text =
$"总分:{total}" & Environment.NewLine &
$"平均分:{average:N2}"
16.8 什么是 List(Of T)?
List(Of T) 是可动态改变大小的泛型列表。这里的 T 代表元素类型。
Dim names As New List(Of String)()
表示建立一个只保存 String 的列表。
建立 Integer 列表:
Dim scores As New List(Of Integer)()
建立 Student 对象列表:
Dim students As New List(Of Student)()
16.9 Add:动态加入项目
Dim courses As New List(Of String)()
courses.Add("Visual Basic 2026")
courses.Add("C# Programming")
courses.Add("Python Programming")
列表会随着 Add 自动增加容量,不需要事先决定最终项目数量。
16.10 Count 与索引
Dim courses As New List(Of String) From {
"Visual Basic 2026",
"C# Programming",
"Python Programming"
}
Dim count As Integer = courses.Count
Dim firstCourse As String = courses(0)
与数组类似,List 索引也是从 0 开始。
| 数组 | List(Of T) |
|---|---|
| scores.Length | scores.Count |
| scores(0) | scores(0) |
| 通常固定大小 | 可以动态 Add / Remove |
16.11 Remove、RemoveAt 与 Clear
按值删除
courses.Remove("C# Programming")
按索引删除
courses.RemoveAt(0)
清空整个列表
courses.Clear()
16.12 Contains:检查项目是否存在
If courses.Contains("Visual Basic 2026") Then
lblResult.Text = "课程已经存在。"
End If
对于简单字符串和基本类型,这非常方便。
16.13 数组还是 List(Of T)?
| 需求 | 数组 | List(Of T) |
|---|---|---|
| 项目数量固定 | 很适合 | 也可以 |
| 经常增加项目 | 不方便 | 很适合 |
| 经常删除项目 | 不方便 | 很适合 |
| 索引访问 | 支持 | 支持 |
| For Each | 支持 | 支持 |
| 初始固定数据 | 简洁 | 也很简洁 |
16.14 List(Of Student):保存对象
上一课已经建立 Student 类。现在可以把多个 Student 对象放进一个 List:
Dim students As New List(Of Student)()
加入对象:
Dim student1 As New Student(
"李明",
"Visual Basic 2026",
88)
students.Add(student1)
也可以直接建立并加入:
students.Add(
New Student(
"王芳",
"C# Programming",
76))
逐个显示对象
For Each student As Student In students
txtOutput.Text &=
student.GetSummary() &
Environment.NewLine &
"--------------------" &
Environment.NewLine
Next
16.15 实作:学生列表管理器
建立新的 Windows Forms 项目:
StudentListManager2026
保留上一课的 Student.vb,再让 Form1 使用 List(Of Student) 保存多个学生对象。
在 Form1 加入:
| 控件 | Name | Text / 设置 |
|---|---|---|
| TextBox | txtStudentName | 输入学生姓名 |
| TextBox | txtCourse | 输入课程名称 |
| TextBox | txtScore | 输入 0–100 |
| Button | btnAddStudent | Text = 加入学生 |
| Button | btnShowAll | Text = 显示全部 |
| Button | btnClearList | Text = 清空列表 |
| TextBox | txtOutput | Multiline = True;ReadOnly = True;ScrollBars = Vertical |
在 Form1 类中建立学生列表
Private ReadOnly students As New List(Of Student)()
加入学生按钮
Private Sub btnAddStudent_Click(
sender As Object,
e As EventArgs) Handles btnAddStudent.Click
Dim studentName As String =
txtStudentName.Text.Trim()
Dim course As String =
txtCourse.Text.Trim()
Dim score As Double
If String.IsNullOrWhiteSpace(studentName) Then
MessageBox.Show("请输入学生姓名。")
txtStudentName.Focus()
Exit Sub
End If
If String.IsNullOrWhiteSpace(course) Then
MessageBox.Show("请输入课程名称。")
txtCourse.Focus()
Exit Sub
End If
If Not Double.TryParse(txtScore.Text, score) Then
MessageBox.Show("请输入有效成绩。")
txtScore.Focus()
Exit Sub
End If
If score < 0 OrElse score > 100 Then
MessageBox.Show("成绩必须介于 0 与 100。")
txtScore.Focus()
Exit Sub
End If
Dim student As New Student(
studentName,
course,
score)
students.Add(student)
MessageBox.Show(
$"学生已加入。当前人数:{students.Count}")
txtStudentName.Clear()
txtCourse.Clear()
txtScore.Clear()
txtStudentName.Focus()
End Sub
显示全部学生
Private Sub btnShowAll_Click(
sender As Object,
e As EventArgs) Handles btnShowAll.Click
txtOutput.Clear()
If students.Count = 0 Then
txtOutput.Text = "目前没有学生资料。"
Exit Sub
End If
txtOutput.Text =
$"学生人数:{students.Count}" &
Environment.NewLine &
Environment.NewLine
For Each student As Student In students
txtOutput.Text &=
student.GetSummary() &
Environment.NewLine &
"--------------------" &
Environment.NewLine
Next
End Sub
清空列表
Private Sub btnClearList_Click(
sender As Object,
e As EventArgs) Handles btnClearList.Click
students.Clear()
txtOutput.Clear()
MessageBox.Show("学生列表已经清空。")
End Sub
16.16 程序执行流程
列表在窗体存续期间持续保存学生对象。
复用第 13 课的 TryParse 和范围检查。
姓名、课程和成绩进入 Student 类。
对象加入动态列表。
逐个调用 student.GetSummary()。
16.17 初学者常见错误
数组索引越界
长度为 5 的数组最后索引是 4,不是 5。
混淆 Length 与 Count
数组通常用 Length;List(Of T) 通常用 Count。
每次点击都重新建立 List
如果列表声明在按钮事件内部,每次事件结束后就无法保存前一次加入的数据。
RemoveAt 使用无效索引
删除前必须确认索引存在,否则会产生异常。
16.18 小练习
- 加入“删除最后一位学生”按钮,先检查 students.Count > 0。
- 加入“显示人数”按钮,只显示 students.Count。
- 建立一个 Integer 数组,计算最高分、最低分和平均分。
- 把三个课程名称放进 List(Of String),练习 Add、Remove 和 Contains。
- 加入学生后,立即调用一个自定义 Sub 更新 txtOutput。
- 尝试建立 List(Of Product),保存多个 Product 对象。
本课复习
- 数组和普通变量最大的区别是什么?
- 数组索引从多少开始?
- 数组元素数量通常使用哪个属性?
- For 与 For Each 在遍历集合时有什么区别?
- List(Of String) 中的 String 表示什么?
- List 使用哪个属性取得当前项目数量?
- Remove 与 RemoveAt 有什么区别?
- 什么时候 List(Of T) 比数组更方便?
- 为什么学生列表应该声明在按钮事件外面?
- List(Of Student) 能解决什么问题?