C# 语言之循环语句
正常情况下,C#应用程序中,在同一个函数下语句的执行顺序是从上往下依次执行。但是,有的时候我们可能需要实现一些更为复杂的逻辑,比如:重复执行一段代码,也叫做循环执行。
在一般的应用程序中,循环可以表示为如下图的形式:
循环的四要素:
初始条件:循环最开始的状态。
循环条件:在什么条件下进行循环,不满足此条件,则循环终止。
状态改变:改变循环变量值,最终不满足循环条件,从而停止循环。
循环体:要反复执行的部分。
C#
给我们提供了多种循环语句:for
,foreach
,while
,do...while
。
for循环
for循环的定义
for循环
是一个允许所编写一个执行特定次数的循环的重复控制结构。通俗点说就是可以重复执行一定次数的循环语句,比如:控制台输出 10 次 “张三”。
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"第{i}个张三");
}
// 输出结果
第0个张三
第1个张三
第2个张三
第3个张三
第4个张三
第5个张三
第6个张三
第7个张三
第8个张三
第9个张三
从上面的示例中,我们可以分析一下循环的四要素。
int i = 0
对应初始条件:循环从0
开始。i < 10
对应循环条件:当i
小于10
时,执行循环,当i
不小于10
循环中止。i++
对应状态改变:i++
表示每执行一次循环i
就在当前的基础上+1
。Console.WriteLine("张三");
对应循环体:也就是我们要循环执行的语句。
for循环的嵌套
多个for
循环之间可以相互嵌套,我们先用for
循环嵌套输出 5x5
的正方行:
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
Console.Write(" .");
}
Console.Write("\n");
}
// 输出
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
从上面的例子我们不难看出,循环嵌套会将多个嵌套的for
循环都执行一遍才会结束。所以,在实际开发中,尽量避免使用多个for
循环嵌套的写法(其它循环同理)。
练习:使用for
循环嵌套输出 9x9
乘法表,如下图:
foreach循环
foreach
可以对一个数组或集合对象进行迭代,遍历对象内容。先来看一个简单的示例:
string[] names = { "赵一", "钱二", "孙三", "李四", "周五", "吴六" };
Console.WriteLine("三年级一班有以下学生:");
foreach (var name in names)
{
Console.WriteLine(name);
}
// 输出
三年级一班有以下学生:
赵一
钱二
孙三
李四
周五
吴六
在上面的示例中,使用foreach
遍历输出了names
集合中的内容。既然都是循环,那使用for
能不能实现呢?当然能。
string[] names = { "赵一", "钱二", "孙三", "李四", "周五", "吴六" };
Console.WriteLine("三年级一班有以下学生:");
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[0]);
}
既然for
和foreach
都能实现循环,那它们之间有什么不同呢?
从编码结构上:
for
循环指定了初始值 也就是i=0
,执行了结束条件,也就是i < names.Length
(集合长度),而foreach
则省略了这些。从底层实现上:
foreach
是通过指针偏移实现的(最初在-1
位置,每循环一次,指针就偏移一个单位),而for
循环是通过当前索引相对零索引的偏移量(通过首地址和地址偏移量)计算实际访问地址实现的。所以,for
循环可是自定义循环初始索引,而foreach
不行。从使用要求上:使用
foreach
语句遍历对象要求对象类型实现了枚举接口IEnumerable
。从使用效率上:
foreach
循环访问时会将对象的值复制到栈上,效率比for
循环要低。
foreach遍历的实现逻辑
在.NET推出了IEnumerable
和IEnumerator
两个接口之后才有了foreach
的用法,使用foreach
的前提是被遍历的对象器实现了IEnumerable
接口。
实现逻辑:集合或数组实现了IEnumerable
接口,并调用GetEnumerator
抽象方法返回IEnumerator
遍历器,通过使用IEnumerator
这个工具来遍历整个类。
IEnumerable<object> obj = new IEnumerable<object>();
IEnumerator tor = obj.GetEnumerator();
while(tor.MoveNext())
{
Console.Write(tor.Current);
}
IEnumerator
中定义了一组方法:
Current
:返回遍历工具所指容器的当前元素。MoveNext
:指向下一个元素,当遍历到没有元素时返回一个false
。
while循环
只要给定条件为 true
,while
循环语句会循环重新执行循环体内的代码。
int i = 1;
while (i > 0)
{
Console.WriteLine("是是是,你说的都对!");
}
上面的例子就是一个简单的while循环语句。但是,如果你执行上面的语句会发现,出现死循环了,一直在输出 “是是是,你说的都对!”
。出现死循环的原因:while
语句如果缺少结束语句(将条件变为false
)将会一直循环下去。
我们可以将上面的示例加一句代码:
int i = 1;
while (i > 0)
{
Console.WriteLine("是是是,你说的都对!");
i = 0;
}
// 输出
是是是,你说的都对!
所以,在实际的开发使用while
循环时,一定要记得加入结束条件,防止出现死循环。一些特殊情况,比如:定时任务,消费服务等例外。
do…while循环
do...while
循环和while
循环类似,但是do...while
循环最少执行一次循环体,因为do...while
循环是在循环的尾部做判断。
int i = 0;
do
{
Console.WriteLine("是是是,你说的都对!");
} while (i > 2);
从上面的例子我们可以看到,在执行完输出操作后,才会去做判断。当判断为 true
时执行下一次循环,判断为 false
跳出循环。do...while
与 while
在使用时一样,也要注意关闭循环,避免引起死循环。