C# 中的 Foreach 循环
C# 提供了 foreach 循环,可以轻松遍历数组或列表等集合中的所有元素。它帮助我们逐个读取每个元素,而无需使用计数器或索引。在本章中,我们将通过示例学习 C# 中的 foreach 循环。
C# 中的 Foreach 循环
C# 中的 foreach 循环 是一种控制流语句,用于遍历集合中的所有元素,而无需使用索引变量或计数器。它会自动从一个元素移动到下一个元素,直到处理完所有元素。
Foreach 循环的流程图
以下是展示 C# 中 foreach 循环 工作原理的 流程图。
Foreach 循环的语法
以下是在 C# 中声明 foreach 循环 的 语法 −
foreach (dataType variableName in collection_name){
// statements to execute
}
在此语法中 −
- dataType 是集合中元素的类型,例如 int 或 string。
- variableName 是当前元素的临时变量。
- in 是连接变量与集合的关键字。
- collection 是要遍历的数组、列表或集合。
- 循环体 是 { } 内部的代码,会为每个元素执行一次。
示例
在这个 示例 中,我们将使用 foreach 循环 遍历一个数字数组,并打印每个数字。
using System;
class Program {
static void Main(){
int[] numbers = { 10, 20, 30, 40, 50 };
foreach (int num in numbers){
Console.WriteLine($"Number: {num}");
}
}
}
在上述程序中,int 是数据类型,num 是循环变量,numbers 是正在遍历的数组。程序的 输出 如下所示 −
Number: 10 Number: 20 Number: 30 Number: 40 Number: 50
C# 中 Foreach 循环的示例
让我们看一下 一些示例,以了解在 C# 中如何使用 foreach 循环遍历数组和列表,并处理每个元素。
Example 1: 使用 Foreach 遍历数组
在这个 示例 中,我们将使用 foreach 循环访问数组的元素并打印它们。数组中的每个数字会自动赋值给循环变量,无需关心其索引。
using System;
class Program {
static void Main(){
// 定义一个数字数组
int[] numbers = { 1, 2, 3, 4, 5 };
// 遍历每个数字并打印
foreach (int number in numbers){
Console.WriteLine(number);
}
}
}
以下是上述程序的 输出 −
1 2 3 4 5
Example 2: 嵌套 Foreach 循环
在这个 示例 中,我们将使用嵌套 foreach 循环遍历二维数组(数组的数组)。外层循环遍历每一行,内层循环遍历该行中的每个元素。
using System;
class Program {
static void Main(){
// 定义数组的数组
int[][] matrix = new int[][]{
new int[] {1, 2},
new int[] {3, 4},
new int[] {5, 6}
};
// 遍历每一行并打印其元素
foreach (int[] row in matrix){
foreach (int item in row){
Console.Write(item + " ");
}
Console.WriteLine(); // 每行结束后换行
}
}
}
以下是上述程序的 输出,它显示了矩阵中每一行的元素。
1 2 3 4 5 6
Example 3: 使用 Foreach 遍历列表
在这个示例中,我们将遍历一个 水果列表。 水果列表 中的每个水果会自动由循环在单独的一行上显示。
using System;
using System.Collections.Generic;
class Program {
static void Main(){
// 创建一个包含水果名称的列表
List<string> fruits = new List<string> { "Apple", "Banana", "Orange" };
// 显示列表中的所有水果
foreach (string fruit in fruits){
Console.WriteLine(fruit);
}
}
}
以下是 输出,它显示了列表的元素。
Apple Banana Orange
Example 4: 使用 Foreach 遍历字典
在这个 示例 中,我们将使用 foreach 循环遍历一个 dictionary,它以 键 存储学生 ID,以 值 存储学生姓名。循环将访问字典中的每个 键值对,并打印 学生 ID 和 姓名。
using System;
using System.Collections.Generic;
class Program {
static void Main(){
// 创建一个包含学生 ID 和姓名的字典
Dictionary<int, string> students = new Dictionary<int, string> {
{ 1, "John" },
{ 2, "Sarah" },
{ 3, "Mike" }
};
foreach (KeyValuePair<int, string> student in students){
Console.WriteLine($"ID: {student.Key}, Name: {student.Value}");
}
}
}
以下是 输出,它显示了学生 ID 和姓名。
ID: 1, Name: John ID: 2, Name: Sarah ID: 3, Name: Mike
限制和常见错误
foreach 循环 使用简单,但有一些 规则 和 限制,我们需要了解它们以避免错误。为了更好地理解它们,我们通过下面的示例逐一说明。
循环变量是只读的
foreach 循环 中使用的 变量 在循环内部不能被重新赋值。我们可以读取其值,但不能改变变量本身。这对于像 int、double 等基本数据类型尤其重要。例如 −
using System;
class Program {
static void Main(){
int[] numbers = { 1, 2, 3, 4, 5 };
foreach (int num in numbers){
num = num * 2; // 错误:不能重新赋值循环变量
Console.WriteLine(num); // 允许:读取值
}
}
}
当我们尝试给 num 赋值新值时,将得到如下 输出 中所示的错误 −
Compilation error (line 11, col 13): Cannot assign to 'num' because it is a 'foreach iteration variable'
迭代时不能修改集合
在使用 foreach 循环 迭代集合时,不能向集合中添加或移除元素。否则将抛出 运行时错误 (InvalidOperationException)。此限制与集合结构有关,而不是循环变量。例如 -
using System;
using System.Collections.Generic;
class Program {
static void Main(){
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
foreach (int num in numbers){
if (num == 3)
numbers.Remove(num); // InvalidOperationException
}
}
}
以下是 输出,清楚地显示了在迭代集合时尝试修改集合时发生的错误。
Unhandled exception. System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.Collections.Generic.List`1.Enumerator.MoveNext() at Program.Main() Command terminated by signal 6
可以修改对象属性
尽管循环变量是只读的,但我们可以在集合中修改引用类型对象(如 class 对象)的属性。这在使用对象列表时非常有用。
以下是一个 示例,我们创建一个 Person 对象列表,并在循环中将每个人的年龄增加 1,而无需重新赋值或改变 person 变量本身。
using System;
using System.Collections.Generic;
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
class Program {
static void Main(){
// 创建人员列表
List<Person> people = new List<Person> {
new Person { Name = "John", Age = 30 },
new Person { Name = "Sarah", Age = 25 }
};
// 将每个人的年龄增加 1
foreach (Person person in people) {
person.Age += 1; // 修改对象属性是允许的
}
// 打印更新后的年龄
foreach (Person person in people){
Console.WriteLine($"{person.Name}: {person.Age}");
}
}
}
以下 输出 显示了在循环中将每个人的年龄增加 1 后的更新年龄。
John: 31 Sarah: 26
Foreach 只能单步向前迭代
foreach 循环 总是逐个元素向前遍历集合。我们不能向后迭代或跳过多个元素。
using System;
class Program {
static void Main(){
int[] numbers = { 10, 20, 30, 40, 50 };
// 使用 foreach 尝试向后迭代是不可能的
foreach (int num in numbers){
// 不能直接访问前一个元素
Console.WriteLine(num);
}
}
}
以下是上述程序的 输出,显示了向前遍历后的元素。
10 20 30 40 50
非索引访问
Foreach 循环 不会自动提供每个元素的索引。如果需要元素的位置,必须使用单独的计数器。例如 −
using System;
class Program {
static void Main(){
string[] names = { "Alice", "Bob", "Charlie" };
int index = 0;
foreach (string name in names){
Console.WriteLine($"Index: {index}, Name: {name}");
index++;
}
}
}
以下是上述程序的 输出,显示了每个元素及其 index。
Index: 0, Name: Alice Index: 1, Name: Bob Index: 2, Name: Charlie
在 Foreach 循环中使用 break 和 continue
有时,我们不希望循环遍历所有元素。我们可能希望根据某些条件提前停止循环或跳过某些项。在 C# 中,我们可以使用关键字 break 和 continue 来控制这一点。
我们将看到两者的示例 −
- 与 foreach 循环一起使用 Break 语句
- 与 foreach 循环一起使用 Continue 语句
与 foreach 循环一起使用 Break 语句
break 语句在特定条件变为 true 时立即停止循环。break 执行后,循环结束,程序继续执行循环外的下一条语句。
示例
在这个示例中,我们打印数组中的数字。当数字达到 15 时,break 语句运行,立即停止循环,因此 15 之后的任何数字都不会被打印。
using System;
class Program {
static void Main(){
// 定义一个数字数组
int[] numbers = { 5, 10, 15, 20 };
// 遍历每个数字,当数字为 15 时停止循环
foreach (int n in numbers){
if (n == 15)
break; // 当 n 为 15 时退出循环
Console.WriteLine(n);
}
}
}
以下是程序的 输出,它显示了在 break 语句停止循环之前打印的数字。
5 10
与 foreach 循环一起使用 Continue 语句
continue 语句跳过当前迭代并移动到集合中的下一个元素。它不会完全停止循环。
示例
在这个 示例中,循环检查数组中的每个数字。当它达到 15 时,continue 语句跳过打印 15,并继续打印剩余的数字。
using System;
class Program {
static void Main(){
// 定义一个数字数组
int[] numbers = { 5, 10, 15, 20 };
// 遍历每个数字并跳过打印 15
foreach (int n in numbers){
if (n == 15)
continue; // 跳过打印 n = 15
Console.WriteLine(n);
}
}
}
运行程序后,输出 显示数组中的所有数字,除了 15。
5 10 20
结论
在本章中,我们学习了 C# 中的 foreach 循环。它允许我们无需使用索引或计数器即可遍历数组、列表或任何集合。我们还看到了如何使用 break 和 continue 来控制循环,并了解了其主要限制。