C#中的语句

news/2025/1/21 14:07:34/

C#提供了各式各样的语句,大多数是由C和C++发展而来,当然,在C#中做了相应修改。语句和表达式一样,都是C#程序的基本组成部分,在本文我们来一起学习C#语句。

1.语句

语句是构造所有C#程序的过程构造块。在语句中可以声明局部变量或常数,调用方法,创建对象或将值赋予变量、属性或字段。语句有很多种,其中,控制语句可以创建循环,如for循环;也可以根据一个布尔表达式的运算结果进行判断,并分支到不同的代码块,如if或switch语句。语句通常以分号终止。

按类别来分,C#的语句如表7-1所示。

本章将重点介绍选择语句、循环语句、跳转语句,其他语句将在相应文章中介绍。其中,checked语句和unchecked语句已在之前章节中介绍过,这里不再赘述。跳转语句中的yield和异常处理语句以及lock语句等将在后续文章中介绍。

2.程序的三种结构

程序的三种常用结构是:

  1. 顺序结构

  2. 分支结构

  3. 循环结构

在C#中,分支结构使用条件语句实现,循环结构使用循环语句实现。下面将分别介绍这三个重要结构。

2.1 顺序结构

C#中最常见的结构就是顺序结构,即按照语句编写的顺序依次执行,如图7-1所示。

2.2 分支结构

实际情况中,只有顺序结构往往是不够的,有时候我们需要根据某一个条件的判定结果来确定程序的执行路径,如图7-2所示。C#中控制分支结构的语句包括:

  1. if......else if......else......语句

  2. switch语句

  3. 三元运算符(?:)

2.3 循环结构

当某一条件成立时,重复执行某段程序(循环体)。C#的循环结构的语句包括:

  1. for循环

  2. while......do......循环

  3. do......while......循环

图7-3分别对应上述三种控制循环结构语句。

3.条件语句

当程序中遇到两种或更多的选择时,就需要使用条件语句对程序的执行路径进行抉择。C#的条件语句包括if语句和switch语句。下面分别讲讲这两种语句。

3.1 if语句

除了要学会if的用法,还要学习配合使用else if和else语句,它们可以配合if完成对其他情况的处理。if语句是最常用的条件判断语句,它根据一个布尔表达式的计算结果来选择要执行的语句,当表达式的结果为true时执行一个操作,为false时则执行另一个操作,如图7-4所示。

语法如下:

下面,我们通过代码进行说明:

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int x = 10;if (x > 5){Console.WriteLine("x值大于5!");}}}
}

如果要解决的问题比较简单,只有一种条件需要判断,那么只需要使用if语句就已足够。但是,问题往往不会这么简单,比如我们买房,不同的楼盘价格不同,不同的楼层价格也不同,如果要写一段程序帮助准用户计算购房价格,就要对各种情况进行处理,即需要根据多个条件进行判断,单纯的一个if已经不够了,这时可以扩展if语句,使用多个else-if来处理多个条件。

其流程如图7-5所示。

语法如下:

if......else if语句的代码示例我们通过代码清单7-1进行介绍,另外,在代码清单7-1中还要对if语句和else if语句的用法进行对比,通过对两段程序的运行结果进行分析,希望以此来告知大家在对多个条件进行判断的时候,如何正确地使用if和else if。对于需要判断多个条件的情况,有两种选择:

  1. 使用多个if

  2. 使用else if排列

下面的代码示例对此进行分析,如代码清单7-1和代码清单7-2所示:

代码清单7-1 使用else if排列

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int x = 30;if (x > 5){Console.WriteLine("x值大于5!");}else if (x > 10){Console.WriteLine("x值大于10!");}else if (x > 20){Console.WriteLine("x值大于20!");}}}
}

运行结果为:

x值大于5!

代码清单7-2 使用多个if语句

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int x = 30;if (x > 5){Console.WriteLine("x值大于5!");}if (x > 10){Console.WriteLine("x值大于10!");}if (x > 20){Console.WriteLine("x值大于20!");}}}
}

运行结果为:

x值大于5!
x值大于10!
x值大于10!

通过对代码清单7-1和代码清单7-2的运行结果进行对比,我们可以发现,前者在条件得到满足以后立即退出条件判断,后面的语句都得不到执行(unreachable);相比之下,后者在第一个条件满足以后继续执行,对后面的所有if条件进行测试执行,因此在打印出"x值大于5!"后仍然继续执行。对代码清单7-2做如下修改,即可达到和代码清单7-1相同的效果,即每个条件测试完后,如果满足则使用return关键字返回,如代码清单7-3所示。

代码清单7-3 使用return关键字

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int x = 30;if (x > 5){Console.WriteLine("x值大于5!");return;}if (x > 10){Console.WriteLine("x值大于10!");return;}if (x > 20){Console.WriteLine("x值大于20!");return;}}}
}

3.2 switch语句

switch语句也可用于对多个条件的判断,但它和if以及else if排列并非完全相同。switch语句是一个控制语句,它通过将控制传递给其体内的一个case语句来处理多个选择,其中case语句只能处理枚举值、常量值和文本值,其语法如下:

switch (表达式) {case 常量表达式1:语句组;break;case 常量表达式2:语句组;break;default:语句组;break;
}

switch语句可以包括任意数目的case实例,但是任何两个case语句都不能具有相同的值。语句体从选定的语句开始执行,直到break将控制传递到case体以外。在每一个case块(包括上一个块,不论它是case语句还是default语句)的后面,都必须有一个跳转语句(如break)。C#不支持从一个case标签显式贯穿到另一个case标签,但有一个例外(这与C++switch语句不同)------当case语句中没有代码时,如代码清单7-4所示。

代码清单7-4 switch语句

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int x = 30;switch (x){case 10:case 20:Console.WriteLine("x值等于20!");break;case 30:Console.WriteLine("x值等于30!");break;default:Console.WriteLine("x值未知!");break;}}}
}

运行结果为:

x值等于30!

上述代码中,x表达式的值为30,switch中的case语句测试紧随其后的常数值,当和x值相等时则执行其下的语句组,其中switch语句内的第9行,case为空语句,因此程序直接从第12行的case语句贯穿到第13行;而第13行的case语句值和x值不匹配,因此也不会进入;第16行和x值匹配,因此系统执行其下的语句组,打印出:"x值等于30!",注意每个case内的语句组都是以break结尾(空语句例外)。第15、18、21行的break语句也可以换成return。注意,这仅限于在switch语句后没有其他语句的情况下,否则switch后的语句将不会被执行。关于return语句的更多细节请参阅后续文章。

4.跳转语句

使用跳转语句执行分支,该语句导致立即传递程序控制。跳转语句中使用下列关键字:

  1. break

  2. continue

  3. return

  4. throw

  5. goto

下面分别介绍以上各关键字的使用。

4.1 break语句

break语句用于终止最近的封闭循环或它所在的switch语句。控制传递给终止语句后面的语句(如果有的话)。下面分别演示break在循环和switch中的用法。

代码清单7-5 break在循环中的使用

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){for (int i = 0; i < 10; i++){if (i == 5){break;}Console.WriteLine("i={0}", i);}}}
}

运行结果为:

i=0
i=1
i=2
i=3
i=4

代码清单7-5 中,循环语句本来要执行一个从0计数到9的循环,但break语句在计数达到5后终止循环,因此if条件后打印i值的语句(第15行)得不到执行。以下代码为break在switch语句中的用法,请参阅代码清单7-4,这里不再赘述。

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int x = 1;switch (x){case 1:Console.WriteLine("x值等于1!");break;case 2:Console.WriteLine("x值等于2!");break;case 3:Console.WriteLine("x值等于3!");break;default:Console.WriteLine("x值未知!");break;}}}
}

4.2 continue语句

continue语句将控制权传递给它所在的封闭迭代语句的下一次迭代。如代码清单7-6所示。

代码清单7-6 continue语句

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){for (int i = 0; i < 10; i++){if (i > 5){continue;}Console.WriteLine("i={0}", i);}}}
}

运行结果为:

i=0
i=1
i=2
i=3
i=4
i=5

在上述代码中,循环语句要执行从0到9的循环,第11行的条件语句判断了变量i的值,当它大于5时即开始下一次循环,这意味着continue以后的语句都将得不到执行。因此运行结果只输出到了当i小于等于5时的结果。

4.3 return语句

return语句终止它出现在其中的方法的执行并将控制返回给调用方法。它还可以返回一个可选值。如果方法为void类型,则可以省略return语句。如代码清单7-7所示。

代码清单7-7 使用return语句

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){string result = HelloWorld("cn");Console.WriteLine(result);result = HelloWorld("en");Console.WriteLine(result);}private static string HelloWorld(string language){string word = string.Empty;switch (language){case "cn":word = "你好!";break;case "en":word = "Hello!";break;}return word;}}
}

运行结果为:

你好!
Hello!

4.4 throw语句

throw语句用于在程序执行期间出现反常情况(异常)时发生信号。异常也是一个对象,该对象的类是从System.Exception派生的,如代码清单7-8所示。

代码清单7-8 throw语句

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){string result = null;try{Console.WriteLine(result.ToString());}catch (Exception){throw;}}}
}

4.5 goto语句

goto语句通常和标签语句配合使用,将程序控制直接传递给标签语句。例如,可用于跳出较深的嵌套循环。另一个通常用法是将控制传递给特定的switch-case标签或switch语句中的默认标签。goto语句要尽量少用,会降低程序代码的可读性。该语句的用法如代码清单7-9所示。

代码清单7-9 goto语句

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){for (int i = 0; i < 100; i++){if (i == 5){goto Exit;}}Exit:Console.WriteLine("Exit!");}}
}

4.6 default语句

default关键字在switch语句中充当默认标签的作用,相当于if条件语句中的else。和else一样,default并不是必需的。

5.标签语句

标签语句的语法如下:

标签:语句

在运行的时候,标签下的语句还是会被执行,标签的作用就是可以让程序从其他位置随时转到标签位置执行,如图7-6所示。

5.1 标签

在标签的有效范围内,可以在goto语句中使用它。我们知道,goto语句可以在块内外转移控制权,但这仅限于从块内到块外。图7-7中的goto标签语句在标签的有效范围外,因此引发编译错误。

5.2 标签语句的有效范围

标签在它所在的整个语句块都是有效的,包括嵌入的块。如果两个同名标签的有效范围重叠,则会引发一个编译期错误。

6.循环语句

通过使用循环语句可以创建循环。循环语句导致嵌入语句根据循环终止条件多次执行。除非遇到跳转语句,否则这些语句将按顺序执行。

C#中共有四种循环语句,它们全部都支持用break来退出循环,用continue来跳过本次循环进入下一次循环。

循环语句使用下述关键字:

  1. while

  2. do......while

  3. for

  4. foreach......in

下面分别介绍。

6.1 while循环

while会先检查一个表达式的值,如果值为true则执行一个语句或语句块,直到指定的表达式为false停止循环,如代码清单7-10所示。

while循环的语法如下:

while(布尔表达式){//语句或语句块
}

代码清单7-10 while循环

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int i = 0;while (i < 10){Console.WriteLine(i);i++;}}}
}

如代码清单7-10所示,while语句在循环执行语句前会先计算"i<10"表达式的值,如果为true则继续,否则终止循环。

上述代码的运行结果为:

0
1
2
3
4
5
6
7
8
9

6.2 do......while循环

do语句重复执行括在{}里的一个语句或语句块,直到指定的表达式计算为false。do......while循环和while循环最大的不同是:前者比后者多做一次循环,因为while先检查布尔表达式的值后执行循环体语句,do......while先执行循环体语句后检查布尔表达式的值。

do......while循环的语法如下:

do{//语句或语句块
}while(布尔表达式)

在代码清单7-11的示例中,只要变量x小于5,do-while循环语句就开始执行。

代码清单7-11 do......while循环

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int x = 0;do{Console.WriteLine(x);x++;} while (x < 5);}}
}

运行结果为:

0
1
2
3
4

6.3 for循环

for语句一般用于循环过程,在循环开始时需要初始化,然后开始循环执行,当其中的布尔表达式返回false时退出,否则会造成死循环。

for循环的语法为:

for(变量初始化;布尔表达式;迭代表达式){//语句或语句块
}

其中,"变量初始化"、"布尔表达式"、"迭代表达式"这三项都是可选项。"变量初始化"为循环控制变量做初始化,循环控制变量可以有一个或多个(用逗号隔开,这意味着控制变量的类型是一样的);"布尔表达式"为循环控制条件,也可以有一个或多个语句;"迭代表达式"按规律改变循环控制变量的值,例如可以递增或者递减,如图7-8所示。

注意,"变量初始化"、"布尔表达式"和"迭代表达式"都是可选的。如果忽略了条件,就可能产生一个死循环,要用跳转语句(break、return或goto)才能退出。如代码清单7-12所示。

代码清单7-12 省略了"变量初始化"、"布尔表达式"和"迭代表达式"的for循环

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int i = 0;for (; ; ){Console.WriteLine(i++);if (i > 6){break;}}}}
}

如代码清单7-12所示,第10行的for循环省略了"变量初始化"、"布尔表达式"和"迭代表达式",这就造成了一个没有出口的循环,即常说的死循环。为避免这种情况,引入了变量i,通过i的自增以及当i值大于6的时候,通过break语句让循环终止,从而避免了死循环的发生。

上述代码输出如下:

0
1
2
3
4
5
6

接下来,我们来看一个标准的for循环的写法,如代码清单7-13所示:

代码清单7-13 标准的for循环写法

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){for (int i = 0; i < 10; i++){Console.WriteLine(i);}}}
}

输出如下:

0
1
2
3
4
5
6
7
8
9

6.4 foreach......in循环

foreach语句基本为数组和集合专用,用于遍历一个数组或对象集合中的每一个元素,其语法为:

foreach(类型变量in集合){//语句或语句块
}

foreach语句的作用就是,每次循环都取出"集合"中的一个元素并放在"变量"中,然后执行一次"语句或语句块"。注意,在"语句或语句块"中,"变量"是只读的。也就是说,只能访问"变量"的值,而不能为其赋值,如图7-9所示。

foreach循环如代码清单7-14所示。

代码清单7-14 foreach循环

using System;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){int[] array = { 1, 2, 3, 4, 5 };foreach (int i in array){Console.WriteLine(i);// i = 0; // 这行代码被注释掉了,因为 foreach 迭代变量是只读的}}}
}

7.using语句

这里的using是语句,而非using指令,using指令为导入指定命名空间,而using语句则是为确保正确使用IDisposable对象的方便语法。这里所谓正确使用指的是,当使用完毕实现了IDisposable接口的对象以后自动调用它的Dispose()方法。

其语法为:

using(局部变量声明及初始化语句,多个使用逗号分隔){//语句或语句块
}

其中的局部变量声明部分负责声明在"语句或语句块"中使用的对象变量,可以声明多个变量,以逗号隔开即可。下面的代码是使用using语句前的用法,可以看到,通过将font1对象放入try块中,并在finally块中调用使用完的font1变量的Dispose()方法释放资源,如图7-10所示。

不使用using语句的示例如代码清单7-15所示。

代码清单7-15 不使用using语句的示例

using System;
using System.Drawing;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){Font font1 = new Font("Arial", 10.0f);try{byte charset = font1.GdiCharSet;}finally{if (font1 != null)font1.Dispose();}}}
}

那么使用using语句后会是怎样的呢?下面对上述代码进行改写,如代码清单7-16所示,font1的声明和初始化放在了using语句中,这点一定要注意,不能仅仅进行声明,还必须包括初始化,如果要使用多个对象就直接在font1对象的初始化语句后使用逗号分隔直接加即可。从第10行到第13行为相关资源的有效范围,出了这个范围CLR自动调用相关对象的Dispose方法。因此,这里使用的资源必须是实现了IDisposable的对象。使用using语句进行改写后的示例如代码清单7-16所示。

代码清单7-16 使用using语句进行改写后的示例

using System;
using System.Drawing;namespace ProgrammingCSharp4
{public class StatementSample{static void Main(){using (Font font1 = new Font("Arial", 10.0f)){byte charset = font1.GdiCharSet;}}}
}

注:Dispose方法是用于释放对象占用的非托管资源(如文件句柄、数据库连接、网络连接、图形资源等)的一种机制。它是 IDisposable 接口的一部分。


http://www.ppmy.cn/news/1564970.html

相关文章

数据结构-LinkedList和链表

1.链表 1.1为什么要引入链表 上一篇文章中我们介绍了ArrayList&#xff0c;ArrayList的底层是通过数组实现的&#xff0c;具有随机访问效率高等特点&#xff0c;那么我们为什么还需要引入链表呢? 这是因为ArrayList底层通过数组实现&#xff0c;当在ArrayList任意位置(除了…

记录一下OpenCV Contrib 编译踩的坑

最近有需要采用OpenCV Contrib 里面的函数做一下处理&#xff0c;要重新编译&#xff0c;一路编译两三个小时了&#xff0c;记录一下备忘吧。 1、编译前先准备好如下环境 ①visual studio已安装&#xff0c;具体版本和型号根据需求经验来&#xff0c;我看常用的是VS2015、VS201…

用行动回应“实体清单”,智谱发布了一系列新模型

1月15日晚间&#xff0c;美国商务部工业和安全局&#xff08;BIS&#xff09;修订了《出口管制条例》&#xff08;EAR&#xff09;&#xff0c;以安全为由在实体清单中分两批增加了25个中国实体。 其中就包括智谱及其子公司&#xff0c;也是国内首家被美国列入实体清单的大模型…

Kubernetes (K8s) 权限管理指南

1. 引言 Kubernetes (K8s) 作为当今最流行的容器编排平台,其安全性至关重要。本指南旨在全面介绍 K8s 的权限管理机制,帮助具有一定基础的读者深入理解并掌握这一关键领域。 © ivwdcwso (ID: u012172506) 2. Kubernetes 安全模型概述 K8s 的安全模型主要包括三个阶段…

使用Python爬虫获取1688网站item_get_company API接口的公司档案信息

一、引言 在当今的商业环境中&#xff0c;获取供应商的详细信息对于采购决策、市场分析和供应链管理至关重要。1688作为中国领先的B2B电子商务平台&#xff0c;提供了丰富的供应商档案信息。通过使用1688的item_get_company API接口&#xff0c;我们可以方便地获取这些信息。本…

nginx实现TCP反向代理

当前实验环境&#xff1a; nginx已安装版本1.11.13 需要动态扩展安装模块nginx_tcp_proxy_module&#xff0c;实现tcp反向代理 实验步骤&#xff1a; 1、nginx当前版本1.11.13&#xff08;nginx已安装&#xff09; # /alidata/nginx/sbin/nginx -v nginx version: nginx/1.1…

OLED--软件I2C驱动__标准库和HAL库

一、标准库---版本一 OLED.c--标准库 #include "stm32f10x.h" #include "OLED_Font.h"/*引脚配置*/ #define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x)) #define OLED_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x…

假设k8s集群规模上千,需要注意的问题有哪些?

在Kubernetes&#xff08;K8s&#xff09;集群规模达到上千个节点时&#xff0c;需要注意的问题相对较为复杂和全面。以下是一些关键的考虑因素和最佳实践&#xff1a; 1. 资源管理 资源配额&#xff1a;设置适当的资源配额&#xff08;Resource Quotas&#xff09;和限制&am…